POJ 3279 反转问题

题目链接http://poj.org/problem?id=3279

题意:有一个n*m的格子,每个格子要么为0,要么为1。我们需要把所有的格子都反转成0,每反转一个格子,它上下左右的格子都会跟着反转。求最少的翻转次数,并输出对应的翻转情况。有多个解时,输出字典序最小的一组。

题目分析:首先我们发现,N,M<=15,数据范围很小,并且翻转不分先后,对一个格子翻转两次,那么相当于没有反转。

假如我们确定了第i行的状态,那么当第i行的状态确定时,第i+1行的状态也就随之确定了,为什么呢?

       对于第i行翻转之后的状态,如果第i行的某个位置[i,j]还存在着一个1,那么这个1必须由翻转[i+1,j]来消除,其他的格子无法再影响[i,j]这个位置了。 而当第i+1行确定了以后,i+2行同理也确定了。所以,我们完全可以通过第i行的翻转情况推出第i+1行的翻转情况

因为数据范围很小,我们可以直接暴力枚举第一行的所有状态,对于每个状态进行判断,记录翻转次数,不断更新答案即可。

代码解释

数组a为原始状态

数组b为用来翻转的(每次翻转前初始b=a)

数组c为记录翻转状态的 (并且c的第一行=数组f,即暴力枚举出的所有状态)

数组d为答案数组,当翻转次数可以更新时,d也随之更新。

void dfs(int x);             枚举出第一行的所有状态,存在f[i]中

int check();                  判断当第一行为此种状态时是否有解,返回值为翻转次数

void fan(int i,int j);    翻转b[i][j]

#include<iostream>
using namespace std;
int m,n,ans=1000;
bool bi=false; //bi判断是否存在解 
int a[20][20],b[20][20],c[20][20],d[20][20];
int f[20];
void dfs(int x);
int check();
void fan(int i,int j);

int main(){
	cin>>m>>n;
	for (int i=1; i<=m; i++)
		for (int j=1; j<=n; j++) cin>>a[i][j];
	dfs(1);
	if (bi==true){
		for (int i=1; i<=m; i++){
			for (int j=1; j<=n; j++) cout<<d[i][j]<<" ";
			cout<<endl;
		}
	} else
	cout<<"IMPOSSIBLE"<<endl;
}

void dfs(int x){
	if (x==n+1){
		//枚举出一种第一行的翻转状态则判断一次。 
		int p=check();
		if (p!=-1)
		{
			bi=true;
			//更新答案 
			if (p<ans){
				ans=p;
				for (int i=1; i<=m; i++)
					for (int j=1; j<=n; j++) 
					d[i][j]=c[i][j];	
			}	
		}
	} else
	for (int i=0; i<=1; i++){
		f[x]=i;
		dfs(x+1);
	}
}

int check(){
	int sum=0;
	for (int i=1; i<=m; i++)
		for (int j=1; j<=n; j++) {
			b[i][j]=a[i][j];
			c[i][j]=0;
		}
	//c数组每次清0,b初始化为a
	 
	for (int i=1; i<=n; i++) {
		c[1][i]=f[i];
		if (c[1][i]==1) {
			fan(1,i);
			sum++;
		}
	}
	//把枚举出来的第一行搬过来
	
	 
	for (int i=2; i<=m; i++)
		for (int j=1; j<=n; j++){
			if (b[i-1][j]==1) {
				c[i][j]=1;
				fan(i,j);
				sum++;
			}
		}
	//b[i-1][j]=1 则需要翻转b[i][j]  
	
	for (int i=1; i<=n; i++)
		if (b[m][i]==1) return -1;	
	//判断最后一行是否全是0,若全是,则此为一个解,否则返回-1	
	return sum;	
}

void fan(int i,int j){
	b[i][j]=(b[i][j]+1)%2;
	b[i][j-1]=(b[i][j-1]+1)%2;
	b[i][j+1]=(b[i][j+1]+1)%2;	
	b[i-1][j]=(b[i-1][j]+1)%2;	
	b[i+1][j]=(b[i+1][j]+1)%2;
}


猜你喜欢

转载自blog.csdn.net/qq_21989927/article/details/81408666