摘要:
选择一个棋子,它和它周围的所有棋子都要翻转一次。求最少要几次可以解决,如果不能解决输出impossible.
这个问题没什么太好的办法,基本上就是枚举法,首先我们选择深度搜索优先(DFS)来解决问题.基本思路就是每次选择一个棋子进行翻转(或者不翻转),如果该棋子已经翻转过,就不需要继续翻转了.检测是否已经达到目标,如果超过16次都没有达到目标,那么它就不可能达成.
同时这个题目还给了我一个教训,忘记在Find函数的一个分支里面写返回了,结果编译器没有报错,而是产生了不确定的行为,导致我没有发现错误,折腾了很久.
#include "stdafx.h"
#include "iostream"
using namespace std;
int board[4][4];
int size = 0;
void flip(int board[][4],int i,int j)
{
size += (board[i][j] == 0?-1:1);
board[i][j] = 1-board[i][j];
if ( i!= 0 )
{
size += (board[i-1][j] == 0?-1:1);
board[i-1][j] = 1-board[i-1][j];
}
if ( i!= 3 )
{
size += (board[i+1][j] == 0?-1:1);
board[i+1][j] = 1-board[i+1][j];
}
if ( j!= 0 )
{
size += (board[i][j-1] == 0?-1:1);
board[i][j-1] = 1-board[i][j-1];
}
if ( j!= 3 )
{
size += (board[i][j+1] == 0?-1:1);
board[i][j+1] = 1-board[i][j+1];
}
}
int Find(int board[][4],int index,int number)
{
int i,j,tempnumber,minnumber = 100;
bool check = (size==0||size==16);
if (check)
{
return number;
}
if(index>=16)
{
return 100;
}
i = index/4,j = index-4*i;
{
flip(board,i,j);
tempnumber = Find(board,index+1,number+1);
minnumber = minnumber<tempnumber?minnumber:tempnumber;
flip(board,i,j);
}
tempnumber = Find(board,index+1,number);
minnumber = minnumber<tempnumber?minnumber:tempnumber;
return minnumber;
}
int main()
{
char s[10];
int i = 0,j = 0,x;
while(i<=3)
{
cin>>s;
j=0;
while(j<=3)
{
board[i][j] = (s[j] == 'b'?0:1);
if(board[i][j] == 0)
size++;
j++;
}
i++;
}
x = Find(board,0,0);
if(x<=16)
{
cout <<x<<endl;
}
else
cout<<"Impossible"<<endl;
return 0;
}