【hdu】1664 different digits【搜索+字符串处理】

来源:互联网 发布:进销存带人力资源软件 编辑:程序博客网 时间:2024/05/16 00:27

题意:

找出给出数的倍数中组成数字最少的那个数,如果组成数字一样输出大小最小的那个数

题解:

刚看到的时候不知所措,根本不知道哪里可以剪枝,也不知道搜索到哪里为止。。。。

point1:该题用到了数论的知识:对于任意的整数n,必然存在一个由不多于两个的数来组成的一个倍数。所以先搜1个数的再搜2个数的就好

证明:因为 a , aa , aaa…… 取 n+1 个,则由鸽笼原理,必有两个模 n 余数相同,相减即得 n 的倍数 m 。而 m 只由 a 、 0 组成。

point2:用vis[余数]判重,只有余数未被访问过的才能被加入队列

point3:不要用string来存当前数的组成,只要记录下当前节点新加的那个数,还有当前节点的前继就好,不然时间会非常恐怖...

#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int N=70000;const int inf=0x3f3f3f3f;bool vis[N];struct node{    int cnt,pre,s,mod;}q[N];int n,save[5],cnt,len;string ans,tmp;void gettmp(int x){    if(x==-1)return;    gettmp(q[x].pre);    tmp+=(q[x].s+'0');}void bfs(){     memset(vis,0,sizeof(vis));     int head=0,tail=-1;     for(int i=1;i<=cnt;i++){        if(!save[i])continue;        node cur;        cur.pre=-1;        cur.s=save[i];        cur.mod=save[i]%n;        cur.cnt=1;        vis[cur.mod]=1;        q[++tail]=cur;     }     while(head<=tail){        int h=head;head++;        if(q[h].cnt>len)return;        if(!q[h].mod){            tmp="";            gettmp(h);            if(q[h].cnt<len){ans=tmp;len=q[h].cnt;}            else if(q[h].cnt==len){if(tmp<ans)ans=tmp;}            return;        }        for(int i=1;i<=cnt;i++){            node next;            next.mod=(q[h].mod*10+save[i])%n;            if(vis[next.mod])continue;            vis[next.mod]=1;            next.cnt=q[h].cnt+1;            next.s=save[i];            next.pre=h;            q[++tail]=next;        }     }}int main(){    while(scanf("%d",&n)&&n){        cnt=1;        len=inf;        for(int i=1;i<=9;i++){            save[1]=i;            bfs();        }        if(len!=inf){            cout<<ans<<endl;            continue;        }        cnt=2;        for(int i=0;i<=9;i++){            save[1]=i;            for(int j=i+1;j<=9;j++){                save[2]=j;                bfs();            }        }        cout<<ans<<endl;    }    return 0;}


0 0