http://poj.org/problem?id=3126
题意给定两个四位素数s,e,求出经过最少的步数由s得到e,每一步的要求是每次只能改变四位数中一位数,并且改变后的数要求也要是素数。
首先求出1000到9999所有的素数,然后有s到e进行bfs,知道遇到e结束。
刚开始自己写完代码之后,测试了一下数据,吓死我了,很慢。心想怎么优化呢。想了很长时间,感觉应该能过啊,不耐烦了还是提交了一下。结果1Y。。。囧啊!!不知道威慑呢么机器上运行的很慢。。
看了一下300多秒。
View Code
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #define maxn 10007 #define inf 9999999 using namespace std; int f[maxn],ans[maxn],b[maxn]; int ct,e,s; //素数筛选法求出1000 --- 9999 的素数 void init() { int i,j; f[0] = f[1] = 1; for (i = 2; i*i < maxn; ++i) { if (!f[i]) { for (j = 2*i; j < maxn; j += i) { f[j] = 1; } } } for (i = 0; i < maxn; ++i) { if (!f[i] && (i >= 1000 && i <= 9999)) { ans[ct++] = i; } } } //判断是否相差1位 bool isok(int x,int y) { int f1 = 0,f2 = 0,f3 = 0,f4 = 0; if (x%10 != y%10) f1 = 1; x /= 10; y /= 10; if (x%10 != y%10) f2 = 1; x /= 10; y /= 10; if (x%10 != y%10) f3 = 1; x /= 10; y /= 10; if (x%10 != y%10) f4 = 1; if (f1 + f2 + f3 + f4 == 1) return true; else return false; } int bfs() { queue<int>q; int i,sum = -1; for (i = 0; i < maxn; ++i) b[i] = inf;//记录到达i点的最短距离 b[s] = 0; q.push(s); while (!q.empty()) { int cur = q.front(); q.pop(); if (cur == e) { sum = b[e]; break; } for (i = 0; i < ct; ++i) { if (isok(cur,ans[i])) { if (b[ans[i]] > b[cur] + 1) { b[ans[i]] = b[cur] + 1; q.push(ans[i]); } } } } return sum; } int main() { int t; memset(f,0,sizeof(f)); init(); scanf("%d",&t); while (t--) { scanf("%d%d",&s,&e); int l = bfs(); if (l != - 1) printf("%d\n",l); else printf("Impossible\n"); } return 0; }