Source
Northwestern Europe 2006
这道题用的是bfs,求最短路径,因为不是二维表,一开始还想不懂用bfs怎么求,后来想想那就把出发点想成球心,下一个点想成球面,每向下一个点,球面就扩大,选择出能到达终点的路径中最小的球面就相当于求最短路径了。
作出的优化:
- 预先生成一张素数表
- 因为是素数,所以最后一位一定为奇数
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
static bool pList[10000];
static int visit[10000];
void initpList(){
memset(pList,false,sizeof(pList));
for(int i=1000;i<=9999;i++){
int mid=floor(sqrt(i)+0.5);
for(int j=2;j<=mid;j++){
if(i%j==0)
break;
if(j==mid)
pList[i]=true;
}
}
}
int main()
{
initpList();
int T;
scanf("%d",&T);
while(T--){
memset(visit,0,sizeof(visit));
int head,dest;
scanf("%d",&head);
scanf("%d",&dest);
queue<int> q;
q.push(head);
visit[head]=-1;
while(!q.empty()){
int t=q.front();
q.pop();
if(t==dest){
break;
}
int num[4];
num[0]=t/1000;
num[1]=(t%1000)/100;
num[2]=(t%100)/10;
num[3]=t%10;
int nextnum;
int rec;
for(int i=0;i<4;i++){
for(int j=0;j<=9;j++){
if(num[i]==j||(i==3&&j%2==0)||(i==0&&j==0))
continue;
rec=num[i];
num[i]=j;
nextnum=num[0]*1000+num[1]*100+num[2]*10+num[3];
num[i]=rec;
if(pList[nextnum]&&visit[nextnum]==0){;
q.push(nextnum);
if(t==head)
visit[nextnum]=1;
else
visit[nextnum]=visit[t]+1;
}
}
}
}
if(head!=dest)
printf("%d\n",visit[dest]);
else
printf("0\n");
}
return 0;
}
学习到的知识:
queue和stack的使用
#include <queue>
#include <stack>
queue<type> q;
stack<type> s;
q.push();
s.push();
q.pop(); //队首出队,但不返回值
s.pop(); //栈顶出栈,但不返回值
q.front(); //获取队首
q.back(); //获取队尾
s.top(); //获取栈顶
q.size();
s.size();
q.empty();//队空返回true
s.empty();
注意的问题:
- 一开始忘记把出发点的visit值设为-1
- num[ ]改了值之后要变回去