POJ分类 枚举专题 poj1753 poj2965

POJ1753

题目大意:给你一个 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

题目大意:

你可能感兴趣的:(枚举,poj)