POJ1753:http://poj.org/problem?id=1753
POJ2965:http://poj.org/problem?id=2965
详细注释见代码:
反思:两道题都很类似,第一道题是翻转四周,第二道题是翻转整行整列,都是求翻转的最小步骤,我们发现这些题目都看似无从下手,只能一个一个试一试(大神勿喷~)
这就是枚举啊,我们使用step来限制树的高度,使用前序遍历来进行翻转,回溯,看似复杂,实际上这两句话仔细体会,再画个树形图,差不多理解就够了.
#include<iostream>
/*
每一次翻转都会影响上下左右进行翻转,截止状态为全黑或者全白,求最少翻转次数
*/
/*
思路:最多翻转16次不同地方,因为两次翻转同一个区域就相当于是,没有翻转过
在1~16次之间dfs搜索,依次搜索,如果有满足的就一定是最优解的情况
搜索方法很有意思,按照先序遍历方法来搜索,但是限制了step,也就是说限制了step的深度,相当于用
一层逻辑把树的下半部分截断了,只考虑上班部分的深度优先搜索,这样无疑保证了每次搜索出来的step
一定是当前最短的step
*/
using namespace std;
bool chess[6][6]={
false}; //四周保持边界,以免出现下标越界的情况
int flag=false;
int step;
int r[5]={
-1,1,0,0,0}; //行和列的上下左右中5个位置都要改变
int c[5]={
0,0,-1,1,0}; //注意:坑:自己也要移动,移动的位置是00
bool isOver()
{
for(int i=1;i<5;++i)
{
for(int j=1;j<5;++j)
{
if(chess[i][j]!=chess[1][1]) return false;
}
}
return true;
}
void flip(int row,int col)
{
for(int i=0;i<5;++i) //注意自己的位置也是要翻转的
{
chess[row<