POJ 1753
来源:互联网 发布:淘宝刷销量平台可靠吗 编辑:程序博客网 时间:2024/06/06 03:24
描述
4*4的方格棋盘,每个棋子有白面和黑面,每个方格中的棋子为白/黑,每轮翻3~5个棋子改变它们的颜色,每轮根据以下规则选择翻面的棋子:
1. 选择16个棋子中的任一个
2. 翻转已选棋子的邻近棋子(左、右、上、下,四个邻近的棋子,如果有就翻)
示例:
b为黑,w为白,若翻第三行第一个,则棋盘变成:
目标是把所有棋子全都白面向上或全都黑面向上,求达成目标的最少回合。
输入
4行,每行4个字符,”w”或”b”,表示给定的棋盘当前状态
输出
从棋盘当前状态达成目标所需的最少游戏回合,若当前已达成目标,输出0,若不可能实现,则输出”Impossible”(不输出引号)
样例输入
bwwb
bbwb
bwwb
bwww
样例输出
4
参考
(1)bfs:http://changgongxiaorong.cn/?p=23
(2)dfs:http://blog.csdn.net/freezhanacmore/article/details/8142014
(3)位运算:http://www.it610.com/article/1987880.htm
根据参考1、参考2用广度搜索和深度搜索都可。
c++实现
(1)广度搜索版
参考1的思路:
广度搜索+枚举+位运算
一个棋子有两种情况,16个棋子,即棋盘有2^16方种情况,即65536种情况,正好一个短整形,所以想到用一个短整形记录棋盘情况,16个位对应棋盘16格,0和1表示黑和白。当状态为0或65535时表示说明全是‘b’或‘w’.
广度搜索使用非递归模式,速度快,用队列实现,元素短整形。全部遍历一遍,剪枝掉重复搜索的情况。
代码:
532K 16MS
#include <iostream>using namespace std;const int MAX = 65535;//[0, 65535]共65536种情况unsigned short myqueue[MAX];//用‘位’保存状态的数组int myrear = 0, mytop = 0;// 头尾指针bool flag[MAX];//是否出现过int num[MAX];//记录翻拍次数/**初始化,w为0,b为1,拼接成16位数字*/void init(){ unsigned short temp = 0; char c; for (int i = 0; i < 16; ++i) { cin >> c; //1左移i位,为当前黑色位置,temp为现有棋盘,temp不断与新数字按位与,生成倒序的棋盘 if(c == 'b'){ temp |= (1 << i); } } myqueue[myrear++] = temp; //追加新的状态 flag[temp] = true; //该状态已经有过}/**now为当前状态,i为要翻转的棋子序号[0,15]*/unsigned short change(unsigned now, int i){ unsigned short temp = 0; temp |= (1 << i); //temp为当前要改变颜色的位置 // 翻转相邻的四个棋子 if((i+1)%4 != 0){ //该棋子不是最右边 temp |= (1 << (i+1)); } if(i%4 != 0){ // 不是最左边 temp |= (1 << (i-1)); } if(i > 3){ // 不是最上边 temp |= (1 << (i-4)); } if(i < 12){ // 不是最上面 temp |= (1 << (i+4)); } return now ^ temp; // 旧状态和新状态相同为0,不同为1}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;}int main(){ init(); if(!bfs()){ cout << "Impossible"; } return 0;}
(2)深度搜索版
参考2的思路:
每次遇到下一个方格有两种处理方法,要么翻转,要么不翻转。
若不翻转方格,则直接处理下一个方格,翻转的方格数不再增加,
若翻转当前方格,则还要翻转相邻的四个方格,然后再处理下一个方格,翻转的总数+1。
- poj 3279 poj 1753
- POJ 1753
- poj&&1753
- poj 1753
- poj 1753
- POJ-1753
- poj-1753
- poj 1753
- poj 1753
- poj 1753
- POJ 1753
- POJ 1753
- poj 1753
- poj-1753
- POJ 1753
- POJ 1753
- POJ 1753
- poj 1753
- 操作系统笔记(一)
- setTimeout中this指向全局windows
- 区间K大数查询
- ArrayList 、Vector 的区别
- File
- POJ 1753
- leetcode63解题报告
- 1020. Tree Traversals (25)
- js与jquery实现搜索框提示文字显示与隐藏
- [绍棠] iOS 在一个UILabel显示不同的字体和颜色
- hbuilder+MUI+html5plus
- 图片循环滚动控件ScrollingImageView
- C语言中的文件流的输入和输出
- 获取AndroidManifest里的信息