HDU-1226 超级密码 (BFS+剪枝)
Problem Description
Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息:
密 码是一个C进制的数,并且只能由给定的M个数字构成,同时密码是一个给定十进制整数N(0<=N<=5000)的正整数倍(如果存在多个满足 条件的数,那么最小的那个就是密码),如果这样的密码存在,那么当你输入它以后门将打开,如果不存在这样的密码......那就把门炸了吧.
注意:由于宝藏的历史久远,当时的系统最多只能保存500位密码.因此如果得到的密码长度大于500也不能用来开启房门,这种情况也被认为密码不存在.
密 码是一个C进制的数,并且只能由给定的M个数字构成,同时密码是一个给定十进制整数N(0<=N<=5000)的正整数倍(如果存在多个满足 条件的数,那么最小的那个就是密码),如果这样的密码存在,那么当你输入它以后门将打开,如果不存在这样的密码......那就把门炸了吧.
注意:由于宝藏的历史久远,当时的系统最多只能保存500位密码.因此如果得到的密码长度大于500也不能用来开启房门,这种情况也被认为密码不存在.
Input
输
入数据的第一行是一个整数T(1<=T<=300),表示测试数据的数量.每组测试数据的第一行是两个整数N(0<=N&
lt;=5000)和C(2<=C<=16),其中N表示的是题目描述中的给定十进制整数,C是密码的进制数.测试数据的第二行是一个整数
M(1<=M<=16),它表示构成密码的数字的数量,然后是M个数字用来表示构成密码的数字.两个测试数据之间会有一个空行隔开.
注意:在给出的M个数字中,如果存在超过10的数,我们约定用A来表示10,B来表示11,C来表示12,D来表示13,E来表示14,F来表示15.我保证输入数据都是合法的.
注意:在给出的M个数字中,如果存在超过10的数,我们约定用A来表示10,B来表示11,C来表示12,D来表示13,E来表示14,F来表示15.我保证输入数据都是合法的.
Output
对于每组测试数据,如果存在要求的密码,则输出该密码,如果密码不存在,则输出"give me the bomb please".
注意:构成密码的数字不一定全部都要用上;密码有可能非常长,不要试图用一个整型变量来保存密码;我保证密码最高位不为0(除非密码本身就是0).
注意:构成密码的数字不一定全部都要用上;密码有可能非常长,不要试图用一个整型变量来保存密码;我保证密码最高位不为0(除非密码本身就是0).
Sample Input
3
22 10
3
7 0 1
2 10
1
1
25 16
3
A B C
Sample output
110
give me the bomb please
CCB
题目分析:由于是求最小的密码,显然就应该用BFS了,其实用DFS加上剪枝(这的剪枝比BFS代码中的剪枝还要多那么一丢丢)也能跑出正确的结果,但仍然会TLE。同余剪枝:当刚出队列的状态转移到下一个时,对n的模已经出现过了,则剪去。
代码如下:
AC的BFS+剪枝:
1 # include<iostream> 2 # include<cstdio> 3 # include<string> 4 # include<queue> 5 # include<cstring> 6 # include<algorithm> 7 using namespace std; 8 struct node 9 { 10 string ans; 11 int val; 12 node(string s,int m):ans(s),val(m){} 13 bool operator < (const node &a) const { 14 if(ans.size()==a.ans.size()) 15 return ans>a.ans; 16 return ans.size()>a.ans.size(); 17 } 18 }; 19 int vis[5005],n,m,c,num[20]; 20 int get() 21 { 22 char ch; 23 cin>>ch; 24 if(ch>='0'&&ch<='9') 25 return ch-'0'; 26 return ch-'A'+10; 27 } 28 void bfs() 29 { 30 memset(vis,0,sizeof(vis)); 31 priority_queue<node>q; 32 for(int i=0;i<m;++i){ 33 if(num[i]==0) 34 continue; 35 string s; 36 if(num[i]<=9) 37 s+=num[i]+'0'; 38 else 39 s+=num[i]-10+'A'; 40 vis[num[i]%n]=1; 41 q.push(node(s,num[i]%n)); 42 } 43 while(!q.empty()) 44 { 45 node u=q.top(); 46 q.pop(); 47 if(u.val==0){ 48 cout<<u.ans<<endl; 49 return ; 50 } 51 if(u.ans.size()>=500) 52 continue; 53 for(int i=0;i<m;++i){ 54 int now=(u.val*c+num[i])%n; 55 if(vis[now]) 56 continue; 57 string s=u.ans; 58 if(num[i]<=9) 59 s+=num[i]+'0'; 60 else 61 s+=num[i]-10+'A'; 62 vis[now]=1; 63 q.push(node(s,now)); 64 } 65 } 66 printf("give me the bomb please\n"); 67 } 68 int main() 69 { 70 int T; 71 scanf("%d",&T); 72 while(T--) 73 { 74 scanf("%d%d",&n,&c); 75 scanf("%d",&m); 76 for(int i=0;i<m;++i) 77 num[i]=get(); 78 sort(num,num+m); 79 if(n==0){ 80 if(num[0]==0) 81 printf("0\n"); 82 else 83 printf("give me the bomb please\n"); 84 continue; 85 } 86 bfs(); 87 } 88 return 0; 89 }
TLE的DFS+剪枝写法:
1 # include<iostream> 2 # include<cstdio> 3 # include<string> 4 # include<cstring> 5 # include<algorithm> 6 using namespace std; 7 int vis[5005],n,m,c,num[20],flag; 8 string aans; 9 int get() 10 { 11 char ch; 12 cin>>ch; 13 if(ch>='0'&&ch<='9') 14 return ch-'0'; 15 return ch-'A'+10; 16 } 17 bool is_smaller(string s1,string s2) 18 { 19 if(s1.size()<s2.size()) 20 return true; 21 if(s1.size()==s2.size()&&s1<s2) 22 return true; 23 return false; 24 } 25 void dfs(string ans,int s) 26 { 27 if(ans.size()>500) 28 return ; 29 if(s==0){ 30 if(!flag){ 31 aans=ans; 32 flag=1; 33 } 34 else{ 35 if(is_smaller(ans,aans)) 36 aans=ans; 37 } 38 return ; 39 } 40 //cout<<ans<<endl; 41 if(flag){ 42 if(aans.size()<ans.size()) 43 return ; 44 if(aans.size()==ans.size()&&ans>aans) 45 return ; 46 } 47 string temp=ans; 48 for(int i=0;i<m;++i){ 49 int ns=(s*c+num[i])%n; 50 if(vis[ns]) 51 continue; 52 if(num[i]<=9) 53 ans+=num[i]+'0'; 54 else 55 ans+=num[i]+'A'-10; 56 vis[ns]=1; 57 dfs(ans,ns); 58 vis[ns]=0; 59 ans=temp; 60 } 61 } 62 int main() 63 { 64 int T; 65 scanf("%d",&T); 66 while(T--) 67 { 68 scanf("%d%d",&n,&c); 69 scanf("%d",&m); 70 for(int i=0;i<m;++i) 71 num[i]=get(); 72 sort(num,num+m); 73 flag=0; 74 memset(vis,0,sizeof(vis)); 75 for(int i=0;i<m;++i){ 76 //cout<<num[i]<<endl; 77 string ans; 78 if(num[i]==0) 79 continue; 80 if(num[i]<=9) 81 ans+=num[i]+'0'; 82 else 83 ans+=num[i]-10+'A'; 84 if(num[i]%n==0){ 85 aans=ans; 86 flag=1; 87 break; 88 } 89 vis[num[i]%n]=1; 90 dfs(ans,num[i]%n); 91 vis[num[i]%n]=0; 92 } 93 if(!flag) 94 printf("give me the bomb please\n"); 95 else 96 cout<<aans<<endl; 97 } 98 return 0; 99 }