hdu1226超级密码 bfs

题目链接:http://icpc.njust.edu.cn/Problem/Hdu/1226/

题目大意是:寻找一个五百位之内的C进制密码,该密码是N的正整数倍,而且只能用给定的数构成密码,求这样的密码最小是多少。思路也不难想到,密码的位数有限,我们可以通过广度优先搜索来搜索目标状态,通过已经拼接好的密码再在最后添加一位就能产生扩展后的密码,也就是层数增加一层,我们可以一层层搜索,但是五百层是绝对不可能通过不剪枝的方法就能搜完的。剪枝的条件是:对于余数相同的数,只让最小的数入队。

证明如下:

假设a=k1*n+q(0<=q<n),b=k2*n+q(0<=q<n),而且 k2>k1,(即a,b余数相同但是a大)那么再进行扩展时,t*a+c=(t*k1)*n+t*q+c,t*b=(t*k2)*n+t*q+c,此时必有t*a>t*b,而且两者模n的余数一定是相等的,如果余数都是0,那么显然t*b+c更加小,所以对于每一种余数,我们只要保存最小数的进行扩展就能保证最终第一个出现的N倍数的数是最小的密码。若选择较大的数成功搜索,则比它小的余数相同的数按照同样的步骤肯定能成为N的倍数。

代码如下:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef unsigned int ui;
  4 typedef long long ll;
  5 typedef unsigned long long ull;
  6 #define pf printf
  7 #define mem(a,b) memset(a,b,sizeof(a))
  8 #define prime1 1e9+7
  9 #define prime2 1e9+9
 10 #define pi 3.14159265
 11 #define lson l,mid,rt<<1
 12 #define rson mid+1,r,rt<<1|1
 13 #define scand(x) scanf("%llf",&x) 
 14 #define f(i,a,b) for(int i=a;i<=b;i++)
 15 #define scan(a) scanf("%d",&a)
 16 #define dbg(args) cout<<#args<<":"<<args<<endl;
 17 #define inf 0x3f3f3f3f
 18 #define maxn 510
 19 #define maxm 5010
 20 int n,m,t,c;
 21 int book[20];
 22 bool vis[maxm];
 23 struct node{
 24     int a[maxn];
 25     int len;//分别保存每一位密码,密码长度
 26 };
 27 int getmod(node tmp)//获取余数的函数 
 28 {
 29     int ans=0;
 30     f(i,0,tmp.len-1)
 31     {
 32         ans=(ans*c+tmp.a[i])%n; 
 33         //应用多项式的计算,由于加法和乘法对于模运算的顺序是不影响的 
 34      } 
 35      return ans;
 36  } 
 37  node cur,ans;
 38  bool flag=false;
 39  void print(node tmp)
 40  {
 41      f(i,0,tmp.len-1)
 42      {
 43          if(tmp.a[i]<10)pf("%d",tmp.a[i]);
 44          else pf("%c",tmp.a[i]-10+'A');
 45      }
 46      putchar('
');
 47  }
 48 
 49 void bfs()
 50 {
 51      queue<node>q;
 52     node st;
 53     st.len=0;
 54     int r;
 55     f(i,1,15)//首位特判,因为不能为零 
 56     {
 57         if(book[i])
 58         {
 59             st.len=1;
 60             st.a[0]=i;
 61              r=getmod(st);
 62                 if(!r)
 63                 {
 64                     flag=1;
 65                     ans=st;
 66                     return;
 67                 }
 68                 if(!vis[r])
 69                 {
 70                     q.push(st);
 71                     vis[r]=1;
 72                 }
 73         }
 74     }
 75         while(!q.empty())
 76         {
 77             cur=q.front();
 78             q.pop();
 79             f(i,0,15)
 80             {
 81                 if(book[i])
 82                 {
 83                     cur.len++;
 84                     cur.a[cur.len-1]=i;
 85                     r=getmod(cur);
 86                     if(!r)
 87                     {
 88                         flag=1;
 89                         ans=cur;
 90                         return;
 91                     }
 92                     if(!vis[r]&&cur.len<500)
 93                     {
 94                         vis[r]=1;
 95                         q.push(cur);
 96                     }
 97                     cur.len--;
 98                 }
 99             }
100         }
101 }
102 int main()
103 {
104     //freopen("input.txt","r",stdin);
105     //freopen("output.txt","w",stdout);
106     std::ios::sync_with_stdio(false);
107     scan(t);
108     while(t--)
109     {
110         mem(book,0);
111         mem(vis,false);
112         flag=false;
113         scan(n);scan(c);
114         scan(m);
115         getchar();
116         char x[3];
117         while(m--)
118         {
119             scanf("%s",x);
120             if(x[0]>='0'&&x[0]<='9')book[x[0]-'0']=1;//保存可访问的数 
121             else book[x[0]-'A'+10]=1;
122         }
123         if(n==0)
124         {
125             if(book[0])//如果要求密码是0的倍数,那么密码就是0,要是给了0就完成,没给0不可以达成目的
126             pf("0
");
127             else pf("give me the bomb please
"); 
128         }
129         else 
130         {
131             bfs();
132             if(flag)
133             {
134                 print(ans);
135             }
136             else pf("give me the bomb please
");
137         }
138     }
139     return 0;    
140  } 
原文地址:https://www.cnblogs.com/randy-lo/p/12513446.html