您的位置:首页 > Web前端

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

2016-07-05 10:16 411 查看
题意:

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

题解:

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

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
;
struct node
{
int cnt,pre,s,mod;
}q
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: