这道题是在搜索进阶专题看的
一开始看不懂不知道怎么运用搜索来解题
后来看了别人的代码理解了几个小时...
最终自己打出来 (自己打出来才是自己的)
好了说一下题目 :
第一个输入T为案例数
然后依次输入n,c,m
n为可被密码整除的数, c为密码的进制数 比如c=2那么密码就是一个二进制数
这个密码可以在m各数中组合 这里要注意是组合!!
因为答案有点大所以需要写一个大数取余的方法 学习了!
因为密码都是有0到15组成而且第一位不为0除非密码是0,所以用一个num数组把出现过的数标记为1
这里if(n)有点剪枝的意思
上代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int n,m,c;
int num[606];
int mark[5050];
struct node
{
int len;//密码长度
int s[606];//用于将数放进队列一个一个遍历
};
int mod(node a)//取余函数
{
int temp=0;
for(int i=0; i<a.len; i++)
{
temp=(temp*c+a.s[i])%n;
}
return temp;
}
void print(node a)//输出
{
for(int i=0;i<a.len;i++)
{
if(a.s[i]<=9)
printf("%d",a.s[i]);
else
printf("%c",a.s[i]+'A'-10);
}
printf("\n");
}
int bfs()
{
node a;
a.len=0;
int r;
queue<node>q;
memset(mark,0,sizeof(mark));
for(int i=1; i<16; i++)
{
if(num[i])
{
a.len=1;
a.s[0]=i;
r=mod(a);
if(!r)
{
print(a);
return 1;
}
else
{
if(!mark[r])
{
mark[r]=1;
q.push(a);
}
}
}
}
while(!q.empty())
{
a=q.front();
q.pop();
for(int i=0;i<16;i++)
{
if(num[i])
{
a.s[a.len]=i;
a.len++;
r=mod(a);
if(!r)
{
print(a);
return 1;
}
else
{
if(!mark[r]&&a.len<499)
{
mark[r]=1;
q.push(a);
}
}
a.len--;
}
}
}
return 0;
}
int main()
{
int T;
char str[6];
scanf("%d",&T);
while(T--)
{
memset(num,0,sizeof(num));
scanf("%d%d%d",&n,&c,&m);
for(int i=0; i<m; i++)
{
scanf("%s",str);
if(str[0]>='0'&&str[0]<='9')
num[str[0]-'0']=1;
else
num[str[0]-'A'+10]=1;
}
if(n)
{
int flag;
flag=bfs();
if(!flag)
printf("give me the bomb please\n");
}
else
{
if(num[0])
{
printf("0\n");
}
else
printf("give me the bomb please\n");
}
}
return 0;
}