POJ 1465 Multiple BFS + 余数判重
2012-08-15 23:34
316 查看
题意是: 给出一个 0 - 4999 的数 N ,在给出 M 个0-9的数,判断这M个数字能不能构成一个数是N的倍数,如果有输出最小的,如果没有输出0。
初次做的 时候犯了很多错误。。。CE TlE 等等各种, 初次做这个题目的时候用了 long long 结果就悲剧了。。。 想了想 long long 明显hold 不住 因为结果可能很大。
不信的话 跑一下这组数据 4999 1 3 位数早就超了20 位。
第二个 令我 wa 爆的是 当 N =0 的时候 一直RE ,还查不出哪里出了错了。。N=0 时特判一下就可。
此题用BFS 。。 这个题好在 用 余数判重剪枝。。
BFS 如果不加以剪枝,一定会搜索的情况会很庞大。所以应该用余数判重 。
为什么可以用余数判重?
A=a*N +e 即A%N =e
B= b*N+e即B%N=e
当A B mod N的余数相同时,如果先出现A 。
在A 后加上一个数 i 时 , 新的数 C = 10 *a*N + 10 *e+i;
同样 B后加上数 i 时 , D = 10*b*N +10*e+i; 由于C D 前边 10*a*N 和 10*b*N 都是N的倍数 ,则C D mod N 的余数都是有 10*e+i 决定的。
于是 C D mod N 同余。
因此 A B 同余 都添加上 i 之后 新的两个数C D也是同余的。在无论添加多少个数,新生成的两个数也是同余的。因此 在A 之后如果不出现 N的倍数 ,则
在B之后也不会出现。 在A 之后出现,那B之后也会出现。 有因为要求求最小值。所以只需要搜索min(A,B)之后的 ,对于另外一个数之后就不用搜索了。
因为对M个排序后,先填入的是小的值,所以 A B 先出现的值小。所以后出现的同余的数 就不用搜索了。。
因此可以余数判重后剪枝。。。。
附上我的代码:
这个程序在poj跑了 32 MS 。。感觉还行 。。 貌似就这个题而言 poj上的数据比zoj强些 ,我的在poj TLE的程序在 zoj上 AC
初次做的 时候犯了很多错误。。。CE TlE 等等各种, 初次做这个题目的时候用了 long long 结果就悲剧了。。。 想了想 long long 明显hold 不住 因为结果可能很大。
不信的话 跑一下这组数据 4999 1 3 位数早就超了20 位。
第二个 令我 wa 爆的是 当 N =0 的时候 一直RE ,还查不出哪里出了错了。。N=0 时特判一下就可。
此题用BFS 。。 这个题好在 用 余数判重剪枝。。
BFS 如果不加以剪枝,一定会搜索的情况会很庞大。所以应该用余数判重 。
为什么可以用余数判重?
A=a*N +e 即A%N =e
B= b*N+e即B%N=e
当A B mod N的余数相同时,如果先出现A 。
在A 后加上一个数 i 时 , 新的数 C = 10 *a*N + 10 *e+i;
同样 B后加上数 i 时 , D = 10*b*N +10*e+i; 由于C D 前边 10*a*N 和 10*b*N 都是N的倍数 ,则C D mod N 的余数都是有 10*e+i 决定的。
于是 C D mod N 同余。
因此 A B 同余 都添加上 i 之后 新的两个数C D也是同余的。在无论添加多少个数,新生成的两个数也是同余的。因此 在A 之后如果不出现 N的倍数 ,则
在B之后也不会出现。 在A 之后出现,那B之后也会出现。 有因为要求求最小值。所以只需要搜索min(A,B)之后的 ,对于另外一个数之后就不用搜索了。
因为对M个排序后,先填入的是小的值,所以 A B 先出现的值小。所以后出现的同余的数 就不用搜索了。。
因此可以余数判重后剪枝。。。。
附上我的代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int num[12]; int n; int m; int exist[5200];// 判重 0 表示没出现 1表示余数出现过 char answer[5200]; // 最后答案存储char 数组里之所以不用string 是因为 每次的 string 的拼接是 O(L)的复杂度 。 如果用java的话 用StringBuilder可以 struct node { // 节点类 把每次的添加的 数 看成在树上添加节点 int fid ; //存储父节点的索引 , 也可用用父节点的指针引用 int num; // 表示 添加入的 数子 int mod; // 表示 当前的数加入后的余数 }tree[5200]; // 因为经过了判重,最多可加入的节点是 N个 也就是 余数的个数。。 struct queue{ // 自己手写的queue int head; int tail; int num[5200]; void push (int a){ num[tail]=a; tail++; } int front(){ return num[head]; } void pop(){ head++; } bool empty(){ if(head==tail) return true; return false; } void clear(){ tail = head = 0; } } qq={0,0}; void init_exist(){ for(int i=0;i<=n;i++){ exist[i]=0; } } void bfs (){ if(!n){ // n=0 特判 cout << 0<<endl; return ; } int idx = 1; qq.clear(); // queue 自己写的方法 表示清空 多组数据用一个队列就够了 init_exist(); for(int i=1;i<=m;i++){ // 现将 这M个数填入队列 int nm = num[i]; int mod = nm%n; if(!num[i]){ // 如果 0 不入队 continue; } if(!mod){ // 余数出现 不入队 cout << nm<<endl; return ; } if(!exist[mod]){ exist[mod] = 1; tree[idx].fid = 0; // 表示是最初的节点。。 无父亲节点。。 tree[idx].num = nm; tree[idx].mod = mod; qq.push(idx++); } } while(!qq.empty()){ int id = qq.front(); qq.pop(); int md=tree[id].mod; for(int i=1;i<=m;i++){ int nm = num[i]; int add_num = md*10+nm; int add_mod = add_num%n; if(!add_mod){ // 判读 余数如果为 0 就输出 。。。。 int ch_idx =1; answer[ch_idx++]=nm+'0'; answer[ch_idx++]=tree[id].num+'0'; while(tree[id].fid){ id = tree[id].fid; answer[ch_idx++]=tree[id].num+'0'; } //一直找到开始的节点 一开始的节点 的fid =0 for(int k = ch_idx-1;k>=1;k--){ // 逆向填入的值 逆向输出。。。。 printf("%c",answer[k]); } cout <<endl; return ; } if(!exist[add_mod]){ exist[add_mod] = 1; tree[idx].fid = id; // 添加新的节点 tree[idx].num = nm; tree[idx].mod =add_mod; qq.push(idx++); } } } cout << 0<<endl; return ; } int main(){ while(scanf("%d",&n)!=EOF){ scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d",&num[i]); } sort(num+1,num+m+1); bfs(); } return 0; }
这个程序在poj跑了 32 MS 。。感觉还行 。。 貌似就这个题而言 poj上的数据比zoj强些 ,我的在poj TLE的程序在 zoj上 AC
相关文章推荐
- POJ 1465/ ZOJ 1136 : Multiple - BFS,余数判重
- POJ1465 Multiple——Bfs+余数判重——Pku1465
- Poj 1465 Multiple BFS+余数判重
- POJ 1465 Multiple(用BFS求能组成的n的最小倍数)
- poj 1465 Multiple 静态节点+余数判重+非STL队列的广搜
- POJ 1465 Multiple (BFS,同余定理)
- POJ 1465-Multiple(BFS-最小整倍数)
- POJ 1465 Multiple (BFS,同余定理)
- POJ 1465 Multiple(BFS+同于定理+打印路径)
- POJ 1465 Multiple BFS
- (BFS)poj1465-Multiple
- poj 1465 bfs,余数判重
- ZOJ 1136 Multiple BFS(POJ 1465)
- POJ1426-Find The Multiple (BFS 余数)
- POJ-1426-Find The Multiple【BFS】
- poj Find The Multiple(DFS,BFS)
- POJ 1465 Multiple
- POJ1465 Multiple BFS+同余判重
- 【原】 POJ 1426 Find The Multiple BFS搜索 解题报告
- POJ-1465-bfs,同余剪枝