题目大意:给你一个 4X4 的棋盘,每次操作你可以反转一个棋子,但是附加着把上下左右相邻的棋子也反转。
如果经过一定次数的操作可以使棋子变得全相同,就输出操作数;反之,就输出impossible。
思路:想到了用0 1替换a、b,从而简化操作,然而对递归回溯并不是理解的很透彻,看的别人的代码才勉强写出来,太弱了,弱弱要变强!
#include<iostream>//POJ1753
#include<cstdio>
#include<algorithm>//反转i次后,如果不能颜色一样,那么就再翻转一次,即i+1次
using namespace std;//反转偶数次和没有进行反转是相同的
char str;//
int digit[6][6];
int flag,step;
//int go[4][2]={1,0,-1,0,0,1,0,-1};
int r[]={-1,1,0,0,0};//便于翻棋操作
int c[]={0,0,-1,1,0};
//判断是否颜色已经完全一样
bool Judge(void)
{
for(int i=1;i<5;i++)
for(int j=1;j<5;j++)
if(digit[i][j]!=digit[1][1])
return false;
return true;
}
//对棋子及其周边的棋子进行反转
void flip(int row,int col)//翻棋
{
int i;
for(i=0;i<5;i++)
digit[row+r[i]][col+c[i]]=!digit[row+r[i]][col+c[i]];
return;
}
void dfs(int row,int col,int deep)
{
if(deep==step)
{
flag=Judge();
return;
}
if(flag||row==5)return;
flip(row,col); //翻棋
if(col<4)
dfs(row,col+1,deep+1);
else
dfs(row+1,1,deep+1);
flip(row,col); //不符合则翻回来
if(col<4)
dfs(row,col+1,deep);
else
dfs(row+1,1,deep);
return;
}
int main(void)
{
char temp;
int i,j;
for(i=1;i<5;i++)
for(j=1;j<5;j++)
{
cin>>temp;
if(temp=='b')
digit[i][j]=true;
}
for(step=0;step<=16;step++) //对每一步产生的可能性进行枚举
{ //至于为什么是16,考虑到4x4=16格,而每一格只有黑白两种情况,则全部的可能性为2^16
dfs(1,1,0);
if(flag)
break;
}
if(flag)
cout<<step<<endl;
else
cout<<"Impossible"<<endl;
return 0;
}
POJ 2965
题目大意:冰箱4X4开关, - 是开,+ 是关,要求开关是全开的。有操作,对某个开关操作,但会同时影响到同行同列的开关(开变成关,关变成开)。让求最少操作数,和操作点的位置。
DFS暂时没做出来,
//
看了别人一篇博客简单的方法,其实也是搜索的思想吧 传送
<span style="font-size:14px;">#include<iostream>
#include<cstdio>
using namespace std;
int a[4][4]={0};
int main()
{
char str;
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
cin>>str;
if(str=='+')
{
for(int t=0;t<4;t++)
{
a[i][t]^=1;//奇数次为1,偶数次为0
a[t][j]^=1;//将同行列的都操作一次
}
a[i][j]^=1;//因为上面循环中操作了操作点两次,所以再来一次(即减一次)
}
}
}
int sum=0;//计算奇数的个数
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
if(a[i][j])
sum++;
printf("%d\n",sum);
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
if(a[i][j])
printf("%d %d\n",i+1,j+1);
}
}
return 0;
}
</span>


475

被折叠的 条评论
为什么被折叠?



