poj---3279---Fliptile(简单搜索)

3279---Fliptile

题目

在这里插入图片描述
在这里插入图片描述

思路

首先看题目的话,这道题目其实可以归类到翻转问题里面,其实无论哪种情况,如果要是确定了第一行的状态,那么下面的翻转就全部确定了,此时,如果想将某一行的1全部翻转为0的话,只需要将1的下面的瓷砖翻转,轮到最后一行的时候,只要检查是否全为0就可以了,如果全为0则方案可行,否则的话此方案不可行,最后想要求出最少的翻转次数只要dfs就可以了,通过二进制枚举第一行的状态,要是字典序最小的话,第一行就从右往左填状态就可以了,注意同一块瓷砖翻转两次等于没有翻转。

题解

#include <iostream>
#include <cstring>
#include <stdio.h>
#include <algorithm>
using namespace std;
int xiang[5][2]={{0,0},{1,0},{-1,0},{0,-1},{0,1}};
int n,m;
int map[50][50],turn[50][50],ans[50][50];
int res,cnt;
int get_num(int x,int y)
{
	int temp=map[x][y];
	for(int i=0;i<5;i++)
	{
		int x_z=x+xiang[i][0];
		int y_z=y+xiang[i][1];
		if(x_z>=0&&x_z<n&&y_z>=0&&y_z<m)
		{
			temp+=turn[x_z][y_z];
		}
	}
	return temp%2;
}
void dfs()
{
	for(int i=1;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			if(get_num(i-1,j))
			{
				cnt++;
				turn[i][j]=1;
			}
			if(cnt>res)
			{
				return;
			}
		}
	}
	for(int i=0;i<m;i++)
	{
		if(get_num(n-1,i))
		{
			return;
		}
	}
	if(cnt<res)
	{
		res=cnt;
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<m;j++)
			{
				ans[i][j]=turn[i][j];
			}
		}
	}
}
int main()
{
	res=10000000;
	cin>>n>>m;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			cin>>map[i][j];
		}
	}
	for(int i=0;i<(1<<m);i++)
	{
		cnt=0;
		memset(turn,0,sizeof(turn));
		for(int j=0;j<m;j++)
		{
			turn[0][m-j-1]=i>>j&1;
			if(turn[0][m-j-1])
			{
				cnt++;
			}
		}
		dfs();
	}
	if(res==10000000)
	{
		cout<<"IMPOSSIBLE"<<endl;
	}
	else
	{
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<m;j++)
			{
				cout<<ans[i][j]<<" ";
			}
			cout<<endl;
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

初见。。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值