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

题目大意:冰箱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>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值