现在的位置: 首页 > 综合 > 正文

POJ 3126 Prime Path BFS

2013年08月22日 ⁄ 综合 ⁄ 共 2759字 ⁄ 字号 评论关闭

题意:给定两个素数 a, b (均为四位数),要求将素数 a 修改成素数 b,每次只能修改一个位置上的数字,且中间的每一步得到的数字也必须是素数。求最少需要的步骤数。若不能将 a 按规定要求换成 b,则输出Impossible.
题解:给出两组代码。

#include <queue>
#include <cstring>
#include <iostream>
using namespace std;

#define N 10000
int step[N];
bool vis[N], prime[N];

void getPrime ()
{
	memset(prime,-1,sizeof(prime));
	prime[0] = prime[1] = 0;
	for ( int i = 2; i <= 100; i++ )
	{
		if ( prime[i] )
			for ( int j = 2; i * j < N; j++ )
				prime[i*j] = 0;
	}
}

int bfs( int a, int b )
{
	memset(vis,0,sizeof(vis));
	memset(step,0,sizeof(step));

	queue<int> Q;
	vis[a] = true;
	Q.push(a);
	int cur, bit, temp, newNum, i;

	while ( !Q.empty() )
	{
		cur = Q.front(); Q.pop();
		if ( cur == b )
			return step[cur];
		bit = cur % 10;                    // 修改个位
		for ( i = -9; i <= 9; i++ )
		{
			temp = bit + i;
			if ( temp >= 0 && temp <= 9 && temp != bit )
			{
				newNum = ( cur / 10 ) * 10 + temp;
				if ( prime[newNum] && ! vis[newNum] )
				{
					step[newNum] = step[cur] + 1;
					vis[newNum] = 1;
					Q.push(newNum);
				}
			}
		}
		bit = cur / 10 - cur / 100 * 10;      //修改十位
		for ( i = -9; i <= 9; i++ )
		{
			temp = bit + i;
			if ( temp >= 0 && temp <= 9 && temp != bit )
			{
				newNum = ( cur / 100 ) * 100 + temp * 10 + cur % 10;
				if ( prime[newNum] && ! vis[newNum] )
				{
					step[newNum] = step[cur] + 1;
					vis[newNum] = 1;
					Q.push(newNum);
				}
			}
		}
		bit = cur / 100 - cur / 1000 * 10;    //修改百位
		for ( i = -9; i <= 9; i++ )
		{
			temp = bit + i;
			if ( temp >= 0 && temp <= 9 && temp != bit )
			{
				newNum = ( cur / 1000 ) * 1000 + temp * 100 + cur % 100;
				if ( prime[newNum] && !vis[newNum] )
				{
					step[newNum] = step[cur] + 1;
					vis[newNum] = 1;
					Q.push(newNum);
				}
			}
		}
		bit = cur / 1000;                  //修改千位
		for ( i = -9; i <= 9; i++ )
		{
			temp = bit + i;
			if ( temp > 0 && temp <= 9 && temp != bit )
			{
				newNum = temp * 1000 + cur % 1000;
				if ( prime[newNum] && !vis[newNum] )
				{
					step[newNum] = step[cur] + 1;
					vis[newNum] = 1;
					Q.push(newNum);
				}
			}
		}
	}
	return -1;
}

int main()
{
	int t, a, b;
	getPrime();
	scanf("%d",&t);
	while ( t-- )
	{
		scanf("%d%d",&a,&b);
		int res = bfs ( a, b );
		if ( res < 0 )
			printf("Impossible\n");
		else
			printf("%d\n",res);;
	}
	return 0;
}


一开是也想用字符串来处理数字的变化,但是找不到合适的方式。刚刚看了Discuss,发现了sprintf 函数。所以把上面的改了下。
//把整数123 打印成一个字符串保存在s 中。sprintf(s, "%d", 123); //产生"123"

#include <queue>
#include <cstring>
#include <iostream>
using namespace std;

#define N 10000
int step[N];
bool vis[N], prime[N];

void getPrime ()
{
	memset(prime,-1,sizeof(prime));
	prime[0] = prime[1] = 0;
	for ( int i = 2; i <= 100; i++ )
	{
		if ( prime[i] )
			for ( int j = 2; i * j < N; j++ )
				prime[i*j] = 0;
	}
}

int bfs( int a, int b )
{
	memset(vis,0,sizeof(vis));
	memset(step,0,sizeof(step));

	queue<int> Q;
	vis[a] = true;
	Q.push(a);
	int cur,newNum;
	while ( ! Q.empty() )
	{
		cur = Q.front();
		Q.pop();
		if ( cur == b )
			return step[cur];
		for ( int i = 0; i < 4; i++ )
		{
			char num[5];
			sprintf(num,"%d",cur);
			for ( int j = 0; j < 10; j++ )
			{
				if ( j == 0 && i == 0 ) continue;
				switch ( i )
				{
				case 0: newNum=j*1000+(num[1]-'0')*100+(num[2]-'0')*10+(num[3]-'0'); break;
				case 1: newNum=j*100+(num[0]-'0')*1000+(num[2]-'0')*10+(num[3]-'0'); break;
				case 2: newNum=j*10+(num[0]-'0')*1000+(num[1]-'0')*100+(num[3]-'0'); break;
			    case 3: newNum=j+(num[0]-'0')*1000+(num[1]-'0')*100+(num[2]-'0')*10; break;
				}
				if ( prime[newNum] && !vis[newNum] )
				{
					step[newNum] = step[cur]+1;
					vis[newNum] = true;
					Q.push ( newNum );
				}
			}
		}
	}
	return -1;
}

int main()
{
	int n, a, b;
	getPrime();
	scanf("%d",&n);
	while ( n-- )
	{
		scanf("%d%d",&a,&b);
		int res = bfs( a, b );
		if ( res < 0 )
			printf("Impossible\n");
		else
			printf("%d\n",res);
	}
	return 0;
}

抱歉!评论已关闭.