POJ 1465 Multiple(BFS+同余剪枝)
http://poj.org/problem?id=1465
题意:给你一个属于[0,4999]的数n和多个十进制单数字.现在要求你输出一个m,这个m是n的最小倍数,且仅有我们之前给出的数字构成.
分析:
首先我们要知道如果存在由m个数位组成且是n的最小倍数的数,那么这个数一定每一位都是指定的数位.所以我们用BFS从0开始扩展.
假设指定数位为1,2,7. 那么我们从0开始扩展可以得到,1,2,7,11,12,17,21,22,27,71,72,77,111,…等等.即按长度扩展即可,但是保证我们扩展的数字得到的每一位都只从被指定的数位中选取即可.
但是如上方法还是会有很多后续可行节点,我们需要去除明显不可行的.假设我们现在遍历到了数字a,且我们扩展了a后面所有的节点.现在我们遍历到了数字b,且b%N==a%N,那么我们应该不扩展b的所有后续节点.为什么呢?
首先a<b(因为我们从数位值小到大扩展的), 假设(b*10+i)%N==0,那么肯定也有(a*10+i)%N==0.(a与b同余,所以这样.仔细想想).所以如果a的一级子孙节点不行的话,b的一级子孙节点也不行.a的x级子孙节点不行的话,b的x级子孙节点也不行.(想想是不是)也就是说a的每一个特定的子孙%N所产生的余数与
b的每一个特定的子孙%N产生的余数一一对应且相同.
所以我用flag[x]=true表示对N求余==x的数已经产生了,以后如果还有这种数生成,直接放弃即可.
还有一个需要注意的点是,我们如何表示BFS扩展的每个状态?由于数可能上千位,如果我们每个节点保存int [1000]肯定不行.我们用下面的方式来:
struct Node
{
int digit;//当前状态的个位值
int r;//当前状态值%N的余数
int pre;//当前状态的个位值的连接指针,用来找到所有当前状态的位
}Q[maxn];
这样就可以极大的节省空间.具体代码体会.
注意原题中的digit特指单位数字,如果是多位数字的话.a应该*100或1000 再加上digit.这样就有点不明确题意了.
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=5000+50;
int n,m;
int digit[10];
bool flag[maxn];
struct Node
{
int digit;
int r;
int pre;
}Q[maxn];
int BFS()
{
memset(flag,0,sizeof(flag));
int front=0,tail=1;
Q[front].digit=0;
Q[front].r=0;
Q[front].pre=-1;
while(front<tail)
{
Node node=Q[front];
int r=node.r; //老余数
for(int i=0;i<m;i++)
{
int nr=(r*10+digit[i])%n; //新余数
if(!flag[nr] && (node.pre!=-1 || digit[i]!=0))//错误,忘写了后面这段,我们要保证后继不能生成0
{
flag[nr]=true;
node.r=nr;
node.digit=digit[i];
node.pre=front;
Q[tail++]=node;
if(nr==0) return tail-1;
}
}
front++;
}
return -1;
}
void print(int ans)
{
if(ans>0)
{
print(Q[ans].pre);
printf("%d",Q[ans].digit);
}
}
int main()
{
while(scanf("%d",&n)==1)
{
scanf("%d",&m);
for(int i=0;i<m;i++) scanf("%d",&digit[i]);
sort(digit,digit+m); //错误,忘写这句了
if(n==0){printf("0\n"); continue;}
int ans=BFS();
if(ans==-1) printf("0\n");
else {print(ans); puts("");}
}
return 0;
}
分享到:
相关推荐
北大POJ1426-Find The Multiple【BFS+同余模】 解题报告+AC代码
北大POJ3009-Curling 2.0【DFS+Vector+回溯+剪枝】 解题报告+AC代码
北大POJ3026-Borg Maze【BFS+Prim】 解题报告+AC代码
北大POJ3733-Changing Digits【DFS+强剪枝】 解题报告+AC代码
北大POJ3373-Changing Digits【DFS+强剪枝】 解题报告+AC代码
NULL 博文链接:https://128kj.iteye.com/blog/1750462
各种搜索算法,配合POJ上的题目,含标程,及各题解题思路。
POJ 1006 源代码——中国剩余定理分析POJ 1006 源代码——中国剩余定理分析POJ 1006 源代码——中国剩余定理分析
西北工业大学POJ试题C++答案代码+课程设计
BFS POJ 3278 POJ 1426 POJ 3126 POJ 3414 POJ 2251 简单搜索技巧和剪枝 POJ 1010 :star: POJ 2362 POJ 1011(搜索+剪枝) POJ 1416 POJ 2676 POJ 1129:white_question_mark: 数据结构 串 POJ 1016 POJ 1035 POJ ...
北大POJ1207-The 3n + 1 problem 解题报告+AC代码
2505 2521 2538 2546 2551 2590 2593 2601 2665 2680 2739 2752 2761 2762 2777 2800 2891 2893 2992 3030 3041 3132 3159 3187 3204 3270 3277 3281 3297 3321 3414 3436 3461 3650 3663 3664 3672 3740
POJ 3131 双向BFS解立体八数码问题
北大POJ1006-Biorhythms【中国剩余定理】 解题报告+AC代码
北大POJ初级-简单搜索 解题报告+AC代码
POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类
1011,1012,1013,1014,1015,1017,1026,1028,1032,1035,1041,1046,1129 1149 1154 1165 1182 1185 1190 1191 1201 1251 1273 1275 1276 1286 1322 1338 1363 1364 1401 1456 1459 1564 1579 1637 1657 1658 ...
POJ-2870 Light Up + DFS(1级DFS+1级DFS) + Python - 思维导图 链接:https://blog.csdn.net/xxdragon126/article/details/122095922?spm=1001.2014.3001.5501
poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题...
北大POJ1159-Palindrome 解题报告+AC代码