POJ 1753 Flip Game (枚举)

该博客讨论了POJ 1753题目的解决方案,这是一个关于翻棋子的游戏,目标是通过最少的翻转次数使得棋盘全黑或全白。关键点在于,每个棋子翻转奇数次的效果等同,可以采用DFS方法进行2^16种状态的枚举。同时,利用二进制和异或性质简化问题,将棋盘每一行用二进制串表示,异或操作有助于状态的变化计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:翻棋子,当出现全黑或是全白的时候停止,每次翻转连带着上、下、左、右一块翻转(如果有的话)。问实现全白或是全黑所需最少步数

思路:重点。。。。每个棋子被翻1,3,5,7或2,4,6,8次的效果完全一样。。。。所以,只要对所有棋子考虑翻或者不翻就可以了。总共2^16种状态,强行DFS........GG

然后考虑棋盘每行都可以用一个二进制串来表示,即用int的前4位来表示。

异或的性质:如1000与一个二进制串异或,二进制串的前三位不变,第四位反号(异或0不变,异或1反号)


#include<iostream>
#include<vector>
#include<string>
#include<queue>
/**
* @note 题意:翻棋子,当出现全黑或是全白的时候停止,每次翻转连带着上、下、左、右一块翻转(如果有的话)。问实现全白或是全黑所需最少步数
思路:重点。。。。每个棋子被翻1,3,5,7或2,4,6,8次的效果完全一样。。。。所以,只要对所有棋子考虑翻或者不翻就可以了。总共2^16种状态,强行DFS。。。GG
然后考虑棋盘每行都可以用一个二进制串来表示,即用int的前4位来表示。
异或的性质:如1000与一个二进制串异或,二进制串的前三位不变,第四位反号(异或0不变,异或1反号)
*/
using namespace std;

int field[6] = { 0 };
int state[][4] = { { 8,4,2,1 },{ 12,14,7,3 } };

///读取数据 用int中的前四位来表示棋盘的一行,1表示黑棋
void read()
{
	for (int i = 1; i <= 4; i++) 
	{
		for (int j = 1; j <= 4; j++) 
		{
			field[i] <<= 1;
			char temp;
			cin >> temp;
			if (temp=='b')
			{
				field[i] |= 1;
			}
		}
	}
}

///反转
void flip(int i, int j) 
{
	--j;
	field[i - 1] ^= state[0][j];
	field[i] ^= state[1][j];
	field[i + 1] ^= state[0][j];
}

///判断是否整个棋盘为同一色
bool check() 
{
	return (field[1] == 0 || field[1] == 15)
		&& field[1] == field[2]
		&& field[2] == field[3]
		&& field[3] == field[4];
}

bool find(int n, int i, int j) 
{
	if (n == 0)
	{
		return check();
	}
	j++;
	if (j > 4) 
	{ 
		i += 1, j = 1; 
	}
	if (i > 4)
	{
		return false;
	}

	for (; i <= 4; i++) 
	{
		for (; j <= 4; j++) 
		{
			flip(i, j);
			if (find(n - 1, i, j))
			{
				return true;
			}
			flip(i, j);
		}
		j = 1;
	}
	return false;
}

void work() 
{
	for (int i = 0; i <= 16; i++)
	{
		if (find(i, 1, 0))
		{
			cout << i << endl;
			return;
		}
	}
	cout << "Impossible" << endl;
}

int main() 
{
	read();
	work();
	system("pause");
	return 0;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值