转载http://www.cnblogs.com/shuaiwhu/archive/2012/04/27/2474041.html 作者:Microgoogle
POJ 1753,题目链接http://poj.org/problem?id=1753,翻译一下整个题目的大概意思:
有4*4的正方形,每个格子要么是黑色,要么是白色,当把一个格子的颜色改变(黑->白或者白->黑)时,其周围上下左右(如果存在的话)的格子的颜色也被反转,问至少反转几个格子可以使4*4的正方形变为纯白或者纯黑?
主要思路如下:
1.对于每个格子,它要么反转0次,要么反转1次(当然,它的邻格子也跟着反转),因为它反转偶数次和反转0次的效果是一样的,同理反转奇数次的效果和反转1次的效果是一样的。
2.由于只有16个格子,我们可以选择0个格子,1个格子,2个格子,3个格子......进行反转,总的选择情况为
3.当0个格子被反转时,看它是否为纯色,否则选择一个格子进行反转(有16种选择),看反转后是否为纯色,否则选择两个格子进行反转(有120种选择),看反转后是否为纯色......
4.只要"3过程"中有纯色出现,就停止"3过程",输出相应的被选择的格子个数,结束。如果16个格子都被翻转了,还是没变成纯色,则输出“Impossible”。
/*
POJ 1753 Flip Game (递归枚举)
By Microgoogle
*/
#include <stdio.h>
#include <stdlib.h>
//所有都是白的,或者所有都是黑的
int all_white_or_black(int* bits, int len)
{
int i = 0;
for (i = 0; i < len - 1; i++)
if (bits[i] != bits[i + 1])
return 0;
return 1;
}
//改变一个格子的颜色,并根据其所在位置改变其周围格子的颜色
void change_color(int* arr, int i)
{
arr[i] = !(arr[i]);
int x = i/4;
int y = i%4;
if (y < 3)
arr[i + 1] = !(arr[i + 1]);
if (y > 0)
arr[i - 1] = !(arr[i - 1]);
if (x > 0)
arr[i - 4] = !(arr[i - 4]);
if (x < 3)
arr[i + 4] = !(arr[i + 4]);
}
//递归判断
//这个完全用了前一篇文章的递归方法,只是在else语句中添加了整个图形是否为纯色的判断而已
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;
//在这里生成arr的副本
int* new_arr = (int*)malloc(sizeof(int)*16);
for (j = 0; j < 16; j++)
new_arr[j] = arr[j];
for (j = NUM - 1; j >=0; j--)
{
change_color(new_arr, result[j]);
}
if (all_white_or_black(new_arr, 16))
{
*last = NUM;
free(new_arr);
break;
}
free(new_arr);
}
}
}
int main()
{
char str[5];
int bits[16];
int count = 15;
int lines = 4;
while (lines--)
{
scanf("%s", str);
int i;
for (i = 0; i < 4; i++)
{
if (str[i] == 'b')
bits[count--] = 1;
else
bits[count--] = 0;
}
}
if (all_white_or_black(bits, 16))
printf("%d\n", 0);
else
{
//生成bits数组的副本
// int* new_bits = (int*)malloc(sizeof(int)*16);
// int i;
// for (i = 0; i < 16; i++)
// new_bits[i] = bits[i];
int j;
//这里last用来接受combine函数里面的NUM,即需要的步数
int last = 0;
for (j = 1; j <= 16; j++)
{
int* result = (int*)malloc(sizeof(int)*j);
// combine(new_bits, 16, result, j, j, &last);
combine(bits, 16, result, j, j, &last);
if (last == j)
{
printf("%d\n", last);
break;
}
//new_bits已被改变,所以要还原为bits
// for (i = 0; i < 16; i++)
// new_bits[i] = bits[i];
free(result);
}
// free(new_bits);
if (j == 17)
printf("Impossible\n");
}
return 0;
}