Time Limit: 1000MS | Memory Limit: 32768K | |
Total Submissions: 6936 | Accepted: 1495 |
Description
Input
Output
Sample Input
22 3 7 0 1 2 1 1
Sample Output
110 0
Source
Southeastern Europe 2000
这道题由于数据的规模,在优化上有一个很好的剪枝,会节省下不少内存和时间,就是余数判重,这个优化在别人的题解里肯定说的很多我就不再多嘴了,其次再说这个BFS,在宽搜之前要对m个数从小到大排一下序,因为题目要求是要最小的倍数,这样你要确定当你向上找到那个父节点的时候,他比之后的数都是小的- -
最后,把得到的答案放在数组里,因为你是从最小的地方开始放的,所以输出的时候从低位到高位,要倒序输出
<( ̄ˇ ̄)/我要好好做题,好好写题解^_^
这是代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; int num[12]; int n,m; int flag[5200]; char answer[5200]; struct node{ int fid; int num; int mod; }tree[5200]; queue<int>qq; void bfs(){ if(!n){ cout<<0<<endl; return; } int idx=1; while(!qq.empty()) qq.pop(); memset(flag,0,sizeof(flag)); for(int i=1;i<=m;++i){ int nm=num[i]; int mod=nm%n; if(!num[i]){ //若当前这个数是0,跳过 continue; } if(!mod){ //若当前这个数对n取余为0,说明这个数是n的倍数,直接输出这个数然后返回 cout<<nm<<endl; return; } if(!flag[mod]){ //若这个数对n取余的余数以前没有取到过(余数判重) 将这个数加入到树中,将这个数的位置进入队列 flag[mod]=1; tree[idx].fid=0; tree[idx].num=nm; tree[idx].mod=mod; qq.push(idx++); } } while(!qq.empty()) //广搜 { int ff=qq.front(); qq.pop(); int md=tree[ff].mod; for(int i=1;i<=m;++i) { int nm=num[i]; int addnum=md*10+nm; int addmod=addnum%n; if(!addmod){ //如果这个数和m个数中的一个组合是n的倍数 int k=0; answer[k++]=nm+'0'; answer[k++]=tree[ff].num+'0'; while(tree[ff].fid) //寻找此点的父节点 { ff=tree[ff].fid; answer[k++]=tree[ff].num+'0'; } for(int kk=k-1;kk>=0;kk--) printf("%c",answer[kk]); printf("\n"); return; } if(!flag[addmod]) //如果当前次的数的组合的余数不为零且未出现过,加入队列 { flag[addmod]=1; tree[idx].fid=ff; tree[idx].num=nm; tree[idx].mod=addmod; qq.push(idx++); } } } cout<<0<<endl; return; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { for(int i=1;i<=m;++i) scanf("%d",&num[i]); sort(num+1,num+m+1); bfs(); } return 0; }