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;
}

 

 

posted on 2012-09-06 17:10  夜->  阅读(227)  评论(0编辑  收藏  举报