(水)POJ-3126 BFS,埃式筛选及黑科技

来源:互联网 发布:淘宝域名怎么填 编辑:程序博客网 时间:2024/04/30 11:54

题目大意:给定两个四位素数a  b,要求把a变换到b,变换的过程要保证  每次变换出来的数都是一个 四位素数,而且当前这步的变换所得的素数    前一步得到的素数  只能有一个位不同,而且每步得到的素数都不能重复。

题目链接:点击打开链接

分析:分析可知这题肯定是用搜索,每次改变某位,每位有0-9(首位无0)10种变法,一共40个方向,可是到底DFS还是BFS还是二分呢?可只二分对这题显然是不太好写的,DFS的话复杂度为O(40^n)估计几年也出不了结果来,,,然后BFS的话O(40*n)肯定是可以过的。BFS是很好写,麻烦的就在数字的转变和素数的判断。这里素数的判断由于是多组数据我们可以用埃式筛选打一个表(怎么实现可以直接看代码,自己思考下就行了,这里朴素的方法也是可以过的)。对于改变一个数字的某一位我们可以用到sprintf和sscanf这2个黑科技来简单的实现,只要先把初始数字v用sprintf打印到字符串里,然后利用字符串的随机访问来改变其中某一位就行了,接下来再用sscanf再输出到v中即可。

附上代码:

#include<iostream>#include<queue>#include<cstring>using namespace std;#define Max 10000+5bool vis[Max], is_prime[Max];int d[Max];int T, a, b;void get_prime()    //打素数表{memset(is_prime, true, sizeof is_prime);for (int i = 2; i*i < Max; i++)if (is_prime[i])for (int j = 2 * i; j < Max; j += i)is_prime[j] = false;return;}int judge(int v,int i,int j){if (!is_prime[v]) return 0;   //不是素数返回0if (i == 1 && j == 0) return 0;  //首位为0返回0char s[6] = "\0";sprintf(s, "%d", v);s[i - 1] = j + '0';   //将第i位改成jsscanf(s, "%d", &v);if (!vis[v]) return v;   //返回改变后的值return 0;}int bfs(){queue<int> q; q.push(a);vis[a] = 1;while (!q.empty()){int v = q.front();q.pop();for (int i = 1; i <= 4; i++)   //枚举40个入口,分别为第i位改成jfor (int j = 0; j <= 9; j++){int t = judge(v, i, j);if (t){vis[t] = 1;d[t] = d[v] + 1;q.push(t);if (t == b) return d[t];}}}return -1;}int main(){scanf("%d", &T);get_prime();while (T--){memset(vis, false, sizeof vis);memset(d, false, sizeof d);scanf("%d%d", &a, &b);if (a == b) printf("0\n");else{int ans = bfs();if (ans == -1) printf("Impossible\n");else printf("%d\n", ans);}}return 0;}



0 0
原创粉丝点击