POJ 1753 Flip Game (递归枚举)

来源:互联网 发布:js模仿360加速球效果 编辑:程序博客网 时间:2024/05/17 07:33

转载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; }