http://poj.org/problem?id=3126
Prime Path
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 20383 | Accepted: 11356 |
Description
The ministers of the cabinet were quite upset by the message from the Chief of Security stating that they would all have to change the four-digit room numbers on their offices.
— It is a matter of security to change such things every now and then, to keep the enemy in the dark.
— But look, I have chosen my number 1033 for good reasons. I am the Prime minister, you know!
— I know, so therefore your new number 8179 is also a prime. You will just have to paste four new digits over the four old ones on your office door.
— No, it’s not that simple. Suppose that I change the first digit to an 8, then the number will read 8033 which is not a prime!
— I see, being the prime minister you cannot stand having a non-prime number on your door even for a few seconds.
— Correct! So I must invent a scheme for going from 1033 to 8179 by a path of prime numbers where only one digit is changed from one prime to the next prime.
Now, the minister of finance, who had been eavesdropping, intervened.
— No unnecessary expenditure, please! I happen to know that the price of a digit is one pound.
— Hmm, in that case I need a computer program to minimize the cost. You don't know some very cheap software gurus, do you?
— In fact, I do. You see, there is this programming contest going on... Help the prime minister to find the cheapest prime path between any two given four-digit primes! The first digit must be nonzero, of course. Here is a solution in the case above.
— It is a matter of security to change such things every now and then, to keep the enemy in the dark.
— But look, I have chosen my number 1033 for good reasons. I am the Prime minister, you know!
— I know, so therefore your new number 8179 is also a prime. You will just have to paste four new digits over the four old ones on your office door.
— No, it’s not that simple. Suppose that I change the first digit to an 8, then the number will read 8033 which is not a prime!
— I see, being the prime minister you cannot stand having a non-prime number on your door even for a few seconds.
— Correct! So I must invent a scheme for going from 1033 to 8179 by a path of prime numbers where only one digit is changed from one prime to the next prime.
Now, the minister of finance, who had been eavesdropping, intervened.
— No unnecessary expenditure, please! I happen to know that the price of a digit is one pound.
— Hmm, in that case I need a computer program to minimize the cost. You don't know some very cheap software gurus, do you?
— In fact, I do. You see, there is this programming contest going on... Help the prime minister to find the cheapest prime path between any two given four-digit primes! The first digit must be nonzero, of course. Here is a solution in the case above.
1033The cost of this solution is 6 pounds. Note that the digit 1 which got pasted over in step 2 can not be reused in the last step – a new 1 must be purchased.
1733
3733
3739
3779
8779
8179
Input
One line with a positive number: the number of test cases (at most 100). Then for each test case, one line with two numbers separated by a blank. Both numbers are four-digit primes (without leading zeros).
Output
One line for each case, either with a number stating the minimal cost or containing the word Impossible.
Sample Input
3 1033 8179 1373 8017 1033 1033
Sample Output
6 7 0题意:从开始的素数,改变一个数字,变成另一个素数。最少要变几次。
思路:把1000-10000中所有的素数存下来,放到数组中,然后拿队列里的素数去遍历这些数字(大约有1100个左右)比较有几位数字不同,要是一位的话就加入队列。
以上思路我个人认为并不好,因为时间复杂度非常高,就拿样例来说,1033到8179,总共判断了1107684次(两个素数有几个数字不同),1373到8017,总共判断了1124660次。这复杂度也能AC,只能说后台数据太弱了。
我的思路:每个数字加入队列就是分成4个小于10的数字分别代表个十百千位。变化4个数字的其中一个,每个数字有大约40种变化情况。样例1033到8179,总共判断了30977次,1373到8017,总共判断了37838次。
附上我的AC代码:(32ms)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
#include<string>
#define LL long long
#define eps 1e-8
using namespace std;
const int mod = 1e7+7;
const int INF = 1e8;
const int inf = 0x3f3f3f3f;
const int maxx = 10100;
const int N = 210;
int f[maxx];//素数判断
int v[maxx];//标记
int n,m,num;
//int sum;
struct node {int a[5],step;}start;//a[0]存千位,a[1]存百位...
int bfs()
{
node p1,p2;
start.step=0;
queue<node>q;
q.push(start);
while(!q.empty())
{
p1=q.front();
q.pop();
for(int i=1;i<10;i++)//改变千位
{
// sum++;
p2=p1;
p2.a[0]=i;
num=p2.a[0]*1000+p2.a[1]*100+p2.a[2]*10+p2.a[3];
if(!f[num]&&!v[num])
{
v[num]=1;
p2.step++;
if(num==m)
return p2.step;
q.push(p2);
}
}
for(int i=0;i<10;i++)//改变百位
{
// sum++;
p2=p1;
p2.a[1]=i;
num=p2.a[0]*1000+p2.a[1]*100+p2.a[2]*10+p2.a[3];
if(!f[num]&&!v[num])
{
v[num]=1;
p2.step++;
if(num==m)
return p2.step;
q.push(p2);
}
}
for(int i=0;i<10;i++)
{
// sum++;
p2=p1;
p2.a[2]=i;
num=p2.a[0]*1000+p2.a[1]*100+p2.a[2]*10+p2.a[3];
if(!f[num]&&!v[num])
{
v[num]=1;
p2.step++;
if(num==m)
return p2.step;
q.push(p2);
}
}
for(int i=0;i<10;i++)
{
// sum++;
p2=p1;
p2.a[3]=i;
num=p2.a[0]*1000+p2.a[1]*100+p2.a[2]*10+p2.a[3];
if(!f[num]&&!v[num])
{
v[num]=1;
p2.step++;
if(num==m)
return p2.step;
q.push(p2);
}
}
}
return -1;
}
int main()
{
for(int i=2; i<=10000; i++)
if(!f[i])
for(int j=i*2; j<=10000; j+=i)
f[j]=1;
int t;
scanf("%d",&t);
while(t--)
{
// sum=0;
memset(v,0,sizeof(v));
scanf("%d%d",&n,&m);
v[n]=1;
if(n==m)
{
printf("0\n");
continue;
}
int cnt=3;
while(n)
{
start.a[cnt--]=n%10;
n/=10;
}
int ans=bfs();
if(ans==-1)
printf("Impossible\n");
else
printf("%d\n",ans);
// printf("%d\n",sum);//计算判断的次数,看时间复杂度的。
}
}
时间复杂度较高的AC代码:(157ms)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
const int maxn=9999;
const int inf=999999;
int prim[maxn];
int isprim[maxn];
bool vis[maxn];
int d[maxn];
int num=0;
bool pan(int a,int b)
{
int ans=0;
while(a)
{
int k=a%10;
int m=b%10;
if(k!=m)ans++;
a/=10;
b/=10;
}
return ans==1;
}
int ans;
void bfs(int s,int stop)//搜索
{
queue<int> q;
memset(vis,0,sizeof(vis));
q.push(s);
vis[s]=true;
d[s]=0;
while(!q.empty())
{
int tmp=q.front();
q.pop();
// cout<<tmp<<endl;
if(tmp==stop)return ;
for(int i=0;i<num;i++)
{
if(!vis[isprim[i]]&&pan(isprim[i],tmp))
{
vis[isprim[i]]=true;
q.push(isprim[i]);
d[isprim[i]]=d[tmp]+1;
}
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int n,i,j,k,t;
num=0;
prim[0]=prim[1]=1;//筛选素数
for(i=2;i<maxn;i++)
if(!prim[i])
{
if(i>1000)isprim[num++]=i;
for(j=i+i;j<maxn;j+=i)
prim[j]=1;
}
int T;
scanf("%d",&T);
while(T--)
{
int a,b;
scanf("%d%d",&a,&b);
d[b]=inf;
bfs(a,b);
if(d[b]!=inf)
printf("%d\n",d[b]);
else
printf("Impossible\n");
}
return 0;
}