Time Limit: 1000MS | Memory Limit: 32768K | |
Total Submissions: 5423 | Accepted: 1179 |
Description
Input
On the first line - the number N
On the second line - the number M
On the following M lines - the digits X1,X2..XM.
Output
An example of input and output:
Sample Input
22
3
7
0
1
2
1
1
Sample Output
110
0
一道比较经典的BFS,剪纸策略真的很强大,值得学习!!
剪枝策略:
若A=n*i+r
B=n*j+r
即A和B同余(i<j),那么若A*10+d[k]能被n整除,那么B*10+d[k]也能被n整除(其中d[k]表示允许出现的一个数字),所以此处就可以做个剪枝了,对于余数相同的数取其最小的。
ps:由于最后的结果可能会很大,所以我在每个状态节点中记录了前一个状态,而且在每个状态中记录当前状态是由哪个数字得到的。
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
struct st
{
int pre;//前一个状态
int r;//余数
int d;//个位数
}w,v;
st q[5000];
int num[10];//数字
bool visit[5000];
int n,m;
void output(int i)
{
if(q[i].pre==-1)
return;
output(q[i].pre);
printf("%d",q[i].d);
}
void bfs()
{
if(n==0)
{
printf("0\n");
return;
}
int front,rear;
bool ok;
front=rear=0;
w.pre=-1;
w.d=0;
w.r=0;
q[rear++]=w;
visit[0]=true;
ok=false;
while(front<rear)
{
w=q[front++];
for(int i=0;i<m;i++)
{
int r=w.r*10+num[i];
if(r>=n&&r%n==0)
{
output(front-1);
printf("%d\n",num[i]);
ok=true;
break;
}
r%=n;
if(!visit[r])
{
visit[r]=true;
v.r=r;
v.pre=front-1;
v.d=num[i];
q[rear++]=v;
}
}
if(ok)
break;
}
if(!ok)
printf("0\n");
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=0;i<n;i++)
visit[i]=false;
for(int i=0;i<m;i++)
scanf("%d",num+i);
sort(num,num+m);//由小到大排序
bfs();
}
return 0;
}