poj 1753 解题报告

 题目描述:

4*4棋盘内有黑(b:black)白(w:white)两色的棋子,用bw表示颜色,选择其中一个反转后,自己和自己上下左右四个方向的棋子均变色,最少反转次数使棋盘全白或全黑。

用户四个一行输入,输入完毕后,打印最少反转次数,不能则打印Impossible




算法分析:

广度搜索+枚举+位运算

一个棋子有两种情况,16个棋子,即棋盘有2的十六次方种情况,即65536,正好一个短整形,所以想到用一个短整形记录棋盘情况,16个位对应棋盘16格。

广度搜索使用非递归模式,速度快,用队列实现,元素短整形。

全部遍历一遍,剪枝掉重复搜索的情况。

(参考了大神的做法)




程序代码:

#include <iostream>
using namespace std;

#define MAX 65535

unsigned short myqueue[MAX];//用‘位’保存状态的数组
int  myrear = 0, mytop = 0;//头尾指针
bool flag[MAX];//是否出现过
int  num[MAX];//记录翻牌次数

void init();
unsigned short change(unsigned now, int i);
bool bfs();

int main(int argc, char *argv[])
{
	init();
	if (!bfs())
	      cout << "Impossible";

	return 0;
}

void init()
{
	unsigned short temp = 0;
	char c;

	for ( int i = 0; i < 16; i++)
	     {
		      cin >> c;
		      if (c == 'b')  
			    temp |= (1<<i);
	      }

	myqueue[myrear++] = temp;
	flag[temp] = true;
}

unsigned short change(unsigned now, int i)
{
	unsigned short temp = 0;

	temp |= (1<<i);
	if ((i+1)%4 != 0)//不是最右边
	      temp |= (1<<(i+1));
	if (i%4 != 0)//不是最左边
	      temp |= (1<<(i-1));
	if (i-4 >= 0)//不是最上边
	      temp |= (1<<(i-4));
	if (i+4 < 16)//不是最下边
	      temp |= (1<<(i+4));

	return now ^ temp;
}

bool bfs()
{
	while (myrear > mytop)
	{
		unsigned short former = myqueue[mytop++];
		for ( int i = 0; i < 16; i++)
		{
			unsigned short temp = change(former, i);
			if (former == 0 || former == 65535)
			{
				cout << num[former];
				return true;
			}
			else if (!flag[temp])//剪枝,防重搜索
			{
				myqueue[myrear++] = temp;
				flag[temp] = true;
				num[temp] = num[former]+1;
			}
		}
	}

	return false;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值