poj 1753 解题报告

来源:互联网 发布:知乎765心理学综合 编辑:程序博客网 时间:2024/05/22 03:31

 题目描述:

4*4棋盘内有黑(b:black)白(w:white)两色的棋子,用bw表示颜色,选择其中一个反转后,自己和自己上下左右四个方向的棋子均变色,最少反转次数使棋盘全白或全黑。

用户四个一行输入,输入完毕后,打印最少反转次数,不能则打印Impossible




算法分析:

广度搜索+枚举+位运算

一个棋子有两种情况,16个棋子,即棋盘有2的十六次方种情况,即65536,正好一个短整形,所以想到用一个短整形记录棋盘情况,16个位对应棋盘16格。

广度搜索使用非递归模式,速度快,用队列实现,元素短整形。

全部遍历一遍,剪枝掉重复搜索的情况。

(参考了大神的做法)




程序代码:

#include <iostream>using namespace std;#define MAX 65535unsigned short myqueue[MAX];//用‘位’保存状态的数组int  myrear = 0, mytop = 0;//头尾指针bool flag[MAX];//是否出现过int  num[MAX];//记录翻牌次数void init();unsigned short change(unsigned now, int i);bool bfs();int main(int argc, char *argv[]){init();if (!bfs())      cout << "Impossible";return 0;}void init(){unsigned short temp = 0;char c;for ( int i = 0; i < 16; i++)     {      cin >> c;      if (c == 'b')      temp |= (1<<i);      }myqueue[myrear++] = temp;flag[temp] = true;}unsigned short change(unsigned now, int i){unsigned short temp = 0;temp |= (1<<i);if ((i+1)%4 != 0)//不是最右边      temp |= (1<<(i+1));if (i%4 != 0)//不是最左边      temp |= (1<<(i-1));if (i-4 >= 0)//不是最上边      temp |= (1<<(i-4));if (i+4 < 16)//不是最下边      temp |= (1<<(i+4));return now ^ temp;}bool bfs(){while (myrear > mytop){unsigned short former = myqueue[mytop++];for ( int i = 0; i < 16; i++){unsigned short temp = change(former, i);if (former == 0 || former == 65535){cout << num[former];return true;}else if (!flag[temp])//剪枝,防重搜索{myqueue[myrear++] = temp;flag[temp] = true;num[temp] = num[former]+1;}}}return false;}


原创粉丝点击