【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;
}
找出给出数的倍数中组成数字最少的那个数,如果组成数字一样输出大小最小的那个数
题解:
刚看到的时候不知所措,根本不知道哪里可以剪枝,也不知道搜索到哪里为止。。。。
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;
}
相关文章推荐
- jquery阻止事件冒泡的3种方式
- 『ExtJS』树 异步加载数据
- 『ExtJS』01 001. ExtJS 4 类的定义
- 『ExtJS』表单(一)常用表单控件及内置验证
- jquery 删除字符串最后一个字符的方法
- JavaScript实现的9大排序算法
- JS(去掉前后空格或去掉所有空格)的用法
- javascript:console.log()是什么js库里的?
- XSS原理剖析【基础篇】【原创】
- JavaScript跨域调用基于JSON的RESTful API
- JavaScript数组方法大全(推荐)
- html5入门(一)
- 剑指offer----从上到下打印二叉树----java实现
- css 注意点
- mvc5+ef6+Bootstrap 项目心得--WebGrid
- jquery获得select option的值 和对select option的操作
- css 选择器
- js第一天知识总结
- bootstrap列数大于12的解决办法
- Web 前端本地化(四)