http://acm.timus.ru/problem.aspx?space=1&num=1495
说是有dp 和 bfs 两种解法 用 dp 不知道其他人怎么做的
我开 int [30][1000000] 直接搜 会超内存 没想到好的方法
所以还是 bfs 吧
结果超时 一直以为Timus 的数据够水 不过 这个题还是超时了
经过不断的优化才过的
思路:
广搜时记录某个 模 是否已经出现 出现了则无需再次入队列 否则入队列 并记录相关信息
当所有的长度在30以内的可用数全出现了时 马上停止搜索 这一步很关键 大大减少时间
代码及其注释:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define LL long long using namespace std; const int N=5000003; struct node { char L,k;//分别为长度 和 此位的值 int mod,f;//取模 和 前驱指向 }qt[N];//手写队列 int I,J; bool had[1000005];//标记这个模是否已出现 int n,nd; void bfs() { while(I<J) { char L=qt[I].L; int mod=qt[I].mod; if(L==30)//已到30 直接停止 {return ;++I;} int mod1=(mod*10+1)%n;//此位用1时的模 int mod2=(mod*10+2)%n;//此位用2时的模 if(had[mod1]==false)//如果没有出现 则入队列 { had[mod1]=true; qt[J].f=I;qt[J].k=1;qt[J].L=L+1;qt[J].mod=mod1; if(mod1==0)//如果搜到答案 停止 {nd=J;return ;} ++J; } if(had[mod2]==false) { had[mod2]=true; qt[J].f=I;qt[J].k=2;qt[J].L=L+1;qt[J].mod=mod2; if(mod2==0) {nd=J;return ;} ++J; } ++I; } } void print(int k)//输出 { if(qt[k].L>1) print(qt[k].f); printf("%d",qt[k].k); } int main() { //freopen("data.txt","r",stdin); while(scanf("%d",&n)!=EOF) { if(n==1||n==2) { printf("%d\n",n); continue; } memset(had,false,sizeof(had)); I=J=0; //初始化 qt[J].L=1;qt[J].k=1;qt[J].mod=1;++J; qt[J].L=1;qt[J].k=2;qt[J].mod=2;++J; had[1]=had[2]=true; nd=-1; bfs();//广搜 if(nd==-1) {printf("Impossible\n");continue;} print(nd); printf("\n"); } return 0; }