题目链接:http://poj.org/problem?id=3126
--------------------------------------------------------
题意:给定两个数,将初始数,每次变换一位而且必须保证变换后的数为素数,要求从初始数到目标数所需要的最小操作次数。
思路:首先是多组测试数据,所以先打个10000以内的素数表,防止每次都去判断。然后就是bfs的想法,每次分别改变个位、十位、百位、千位的值,然后按层次进行遍历,首先到达的情况是最小值的情况。
代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<string> #include<vector> #include<stack> #include<bitset> #include<cstdlib> #include<cmath> #include<set> #include<list> #include<deque> #include<map> #include<queue> using namespace std; typedef long long ll; const double PI = acos(-1.0); const double eps = 1e-6; const int MAXN = 1e4+10; int prime[MAXN]={0}; int vis[MAXN]={0}; struct State{ int i; int step; }state[4*MAXN]; int ini,myend; void initprime(){ for(int i=2;i<MAXN;i++){ int flag =1; for(int j=2;j<i/j+1;j++){ if(i%j==0) flag =0; } if(flag) prime[i]=1; else prime[i]=0; } } void bfs(State st){ queue<State>q; State cur,cnext; st.step=0; vis[cur.i]=1; q.push(st); while(!q.empty()){ cur = q.front(); q.pop(); if(cur.i==myend){ printf("%d\n",cur.step); return; } for(int i=1;i<=9;i++){ cnext.i = cur.i/10*10+i; if(vis[cnext.i]!=1&&prime[cnext.i]==1){ vis[cnext.i]=1; cnext.step = cur.step+1; q.push(cnext); } } for(int i=0;i<=9;i++){ cnext.i = cur.i/100*100+i*10+cur.i%10; if(vis[cnext.i]!=1&&prime[cnext.i]==1){ vis[cnext.i]=1; cnext.step = cur.step+1; q.push(cnext); } } for(int i=0;i<=9;i++){ cnext.i = cur.i/1000*1000+i*100+cur.i%100; if(vis[cnext.i]!=1&&prime[cnext.i]==1){ vis[cnext.i]=1; cnext.step = cur.step+1; q.push(cnext); } } for(int i=1;i<=9;i++){ cnext.i = cur.i%1000+i*1000; if(vis[cnext.i]!=1&&prime[cnext.i]==1){ vis[cnext.i]=1; cnext.step = cur.step+1; q.push(cnext); } } } printf("Impossible\n"); return ; } int main(void){ int T =0; scanf("%d",&T); initprime(); for(int i=0;i<T;i++){ for(int i=0;i<MAXN;i++){ vis[i]=0; } State ele; scanf("%d %d",&ele.i,&myend); bfs(ele); } return 0; }