您的位置:首页 > 其它

POJ 3126 Prime Path (换门牌)

2015-12-21 16:23 246 查看
题目链接POJ 3126

题意:

给出两个数a,b,且a,b均为四位素数,a<b。每次只改变a的一位数字,且改变后的数字仍是四位素数(也就是千位不能变为0),经过若干次操作使得最终从a变为b,问最少经历多少次操作?

思路:

先对四位正整数素数打表,然后用BFS搜索,每次从队列首去除一个元素,判断是否是目标数,否则将由这个数产生的符合条件的数字入队列(先判断是否是目标数)。开两个数组,一个用于记录当前数字是否访问过,一个用于记录到达当前数字的步骤数。

#include <iostream>
#include <queue>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <sstream>
using namespace std;
const int maxn = 10000;
int IsPrime[maxn],vis[maxn],cnt[maxn];
int n, a, b, ans;

int isprime(int n)
{//判断n是否为素数
	for (int i = 2;i*i <= n;i++)
		if (n%i == 0) return 0;
	return 1;
}

void init()
{//对[1000,9999]的正整数进行素数打表
	for (int i = 1000;i < maxn;i++)
		IsPrime[i] = isprime(i);
}

int BFS(int first,int last)
{
	memset(vis, 0, sizeof(vis));//vis[i]=0表示i尚未访问过
	memset(cnt, 0, sizeof(cnt));//cnt[i]表示到达i经历的步骤数
	queue<int> q;
	int v, temp, vtemp, digit[4];
	q.push(first);//将起始数入队列
	vis[first] = 1;//起始数访问过了
	while (!q.empty())//队列非空时
	{
		v = q.front();//取队首元素
		q.pop();//队首元素出队列
		if (v == last) return cnt[v];//队首元素==目标值,返回次数
		digit[0] = v / 1000;//千位
		digit[1] = v / 100 % 10;//百位
		digit[2] = v / 10 % 10;//十位
		digit[3] = v % 10;//个位
		for (int i = 0;i < 4;i++)
		{//对每个数需要改变个十百千每个位上的数字
			temp = digit[i];
			for (int j = 0;j < 10;j++)
			{//每个位上的数字从0到9开始替换
				if (temp != j)
				{//数字不重合
					digit[i] = j;//这样做方便了计算vtemp!
					vtemp = digit[0] * 1000 + digit[1] * 100 + digit[2] * 10 + digit[3];
					if (vtemp > 999 && !vis[vtemp] && IsPrime[vtemp])
					{//千位不为0&&尚未访问过&&是素数
						cnt[vtemp] = cnt[v] + 1;//到达vtemp的步骤数=到达v的步骤数+1
						vis[vtemp] = 1;//标记访问过
						q.push(vtemp);//入队列
					}
					if (vtemp == last) return cnt[vtemp];
				}
			}
			digit[i] = temp;//别忘记替换回来!
		}
	}
	return -1;
}

int main()
{
#ifdef LOCAL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	init();
	while (~scanf("%d", &n))
	{
		while (n--)
		{
			scanf("%d%d", &a, &b);
			ans = BFS(a,b);
			if (ans == -1) printf("Impossible\n");
			else cout << ans << endl;
		}
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: