题目链接:http://poj.org/problem?id=1753
题目大意:有4*4的正方形棋盘,里面有黑白棋子,我们翻转一个棋子会改变它本身以及周围棋子的颜色,求最少多少步可以把所以棋子翻成同色。
思路:首先判断棋盘本身是否为纯色,如果是输出0。
从挑出1个棋子翻转开始,挑出2个翻转,3个,4个……16个,共有2的16次方种翻转方法。
在翻转过程中若已经达成纯色则跳出循环输出答案。
若翻转16个棋子还是没有变成纯色则输出impossible。
代码如下:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
using namespace std;
int panduan(int bitss[])
{
for(int i=0;i<15;i++)
{
if(bitss[i]!=bitss[i+1])
return 0;
}
return 1;
}
void fanzhuan(int num2[],int t)
{
num2[t]=-num2[t];
if(t-4>=1) num2[t-4]=-num2[t-4];
if(t+4<=16) num2[t+4]=-num2[t+4];
if(t+1<=16) num2[t+1]=-num2[t+1];
if(t-1>=1) num2[t-1]=-num2[t-1];
}
void combine(int* arr, int len, int* result, int count, const int NUM, int* last)
{
int i;
for (i=len;i>=count;i--)
{
result[count-1]=i-1;
if (count>1)
{combine(arr, i - 1, result, count - 1, NUM, last);}
else
{
int j = 0;
int new_arr[20];
for (j = 0; j < 16; j++)
{
new_arr[j] = arr[j];
}
for (j = NUM - 1; j >=0; j--)
{
fanzhuan(new_arr,result[j]);
}
if (panduan(new_arr)==1)
{
*last = NUM;
break;
}
}
}
}
int main()
{
int bits[20];
int m=15;
char str[5];
for(int i=1;i<=4;i++)
{
scanf("%s",str);
for(int j=0;j<4;j++)
{
if(str[j]=='b') {bits[m]=1;m--;}
else {bits[m]=-1;m--;}
}
}
if (panduan(bits)==1) cout<<"0"<<endl;
else
{
int new_bits[20];
for (int i=0;i<16;i++)
{
new_bits[i] = bits[i];
}
int j;
int last = 0;
for (j = 1; j <= 16; j++)
{
int* result = (int*)malloc(sizeof(int)*j);
combine(new_bits,16,result,j,j,&last);
if (last == j)
{
printf("%d\n", last);
break;
}
for (int i=0;i<16;i++)
{
new_bits[i] = bits[i];
}
}
if (j == 17)
{
printf("Impossible\n");
}
}
return 0;
}