05-flip game-boj

背景描述:

翻转游戏:在一个4x4的格子。每个格子里一个棋子,棋子有黑白两面。

       规则:每次翻转一个棋子,该棋子翻转的同时,要翻转其相邻的所有棋子,即左侧、右侧、上侧、下侧。因此每次翻转可能翻转3-5次棋子。多次翻转直到所有棋子的颜色一样则完成。 

问题:给你一个任意时刻的棋盘的棋子状态图,求到达全黑或全白的最短步数。例子如下:

             

Sample Input

1

bwwb

bbwb

bwwb

bwww

Sample Output

4

分析:
刚开始看的时候没有任何思路。看了网上的思路。
        具体是一个矩阵,求该矩阵到达某一状态所需的最短步数。有两种方案
        BFS:
即宽度枚举所有状态,把一步的所有状态考察个遍。比如从某个状态起,查看每个棋子翻转后的状态,如果有成功状态则返回,否则,对于每一个子状态继续枚举。
       DFS:
                即深度枚举所有状态,最多有16步,对于一步的,针对每个棋子深度搜索。两步也是。以此类推。
     下面是 抄的别人的dfs的代码:
    
    
#include<iostream>
using namespace std;
char chess[6][6]={'*'};
bool Chess[6][6]={0};
bool finish()//判断是否全黑或全白
{
	int i,j;
	for(i=1;i<=4;i++)
		for(j=1;j<=4;j++)
			if(Chess[i][j]!=Chess[1][1])
				return false;
	return true;
}
void flip(int m,int n)//翻棋操作
{
	Chess[m][n]=!Chess[m][n];
	Chess[m-1][n]=!Chess[m-1][n];
	Chess[m+1][n]=!Chess[m+1][n];
	Chess[m][n+1]=!Chess[m][n+1];
	Chess[m][n-1]=!Chess[m][n-1];
}
bool dfs(int x,int y,int now,int deep)
{
	if(now>deep)   return false;//判断是否超出枚举范围
	if(finish())   return true;
	for(int i=x;i<=4;i++)
		for(int j=y;j<=4;j++)
		{
			flip(i,j);//翻棋
			if(j<4)//同一行的没翻完继续翻,翻完就翻下一行
			{if(dfs(i,j+1,now+1,deep))  return true;}//同一行
			else
			{if(dfs(i+1,1,now+1,deep))  return true;}//下一行
			flip(i,j);//不成功则翻回最后一粒子重新搜索下一个目标位
			if(j==4)//如果一列翻完且搜索失败,下一轮翻棋重新由下一行第一列开始
				y=1;
		}
	return false;
}
int main()
{
    int m;
    while(cin>>m)
    {
		for( int k = 0; k < m; k++ )
		{
			int i,j,step;
			bool flag=false;
			for( i = 0; i < 6;i++ )
			{
				for( j = 0; j < 6; j++)
				{
					chess[i][j]='*';
					Chess[i][j]= 0;
				}
			}
			for(i=1;i<=4;i++)
			{
				for(j=1;j<=4;j++)
				{
					cin>>chess[i][j];
					if(chess[i][j]=='b')
						Chess[i][j]=1;
				}
			}
			for(step=0;step<=16;step++)//状态总共2^16种,即翻棋有翻0,1,2.....16粒子,共17种选择
			{
				if(dfs(1,1,0,step))
				{
					flag=true;
					break;
				}
			}

			if(flag)
				cout<<step<<endl;
			else
				cout<<"Impossible\n";
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值