Flip Game POJ-1753 (位运算&DFS)

传送门

思路:每个位置至多翻转一次,一开始我以为在位置 A A A翻一次,然后进行其他影响 A A A的操作,再翻转 A A A的操作是对 A A A的贡献有影响的,但是仔细想想,只要翻转 A A A的相邻位置, A A A也会进行相应翻转,所以 A A A翻转两次最后等于没翻转。

所以可以考虑暴力 2 16 2^{16} 216位运算。
或者贪心步数从小到 d f s dfs dfs

位运算:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e3+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
#define il inline
int a[5][5],d[4][2]={0,1,0,-1,1,0,-1,0};
char c;
void fun(int x,int y){
	a[x][y]^=1;
	for(int i=0;i<4;i++){
		int nx=x+d[i][0],ny=y+d[i][1];
		if(nx>=0&&nx<4&&ny>=0&&ny<4) a[nx][ny]^=1;
	}
}
bool check(){
	for(int i=0;i<4;i++)
		for(int j=0;j<4;j++)
			if(a[i][j]!=a[0][0]) return 0;
	return 1;
}
int main(){
	for(int i=0;i<4;i++)
		for(int j=0;j<4;j++)
			cin>>c,a[i][j]=c=='b'?1:0;
	int ans=inf;
	for(int i=0;i<(1<<16);i++){
		int s=0;
		for(int j=0;j<16;j++){
			if((i>>j)&1){
				s++;
				int x=j/4,y=j%4;
				fun(x,y);
			}
		}
		if(check()) ans=min(ans,s);
		for(int j=0;j<16;j++)
			if((i>>j)&1){
				int x=j/4,y=j%4;
				fun(x,y);	
			}
	}	
	printf(ans==inf?"Impossible":"%d\n",ans);
 	return 0;
}

d f s dfs dfs

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e3+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
#define il inline
int a[5][5],d[4][2]={0,1,0,-1,1,0,-1,0};
char c;
void fun(int x,int y){
	a[x][y]^=1;
	for(int i=0;i<4;i++){
		int nx=x+d[i][0],ny=y+d[i][1];
		if(nx>=0&&nx<4&&ny>=0&&ny<4) a[nx][ny]^=1;
	}
}
bool check(){
	for(int i=0;i<4;i++)
		for(int j=0;j<4;j++)
			if(a[i][j]!=a[0][0]) return 0;
	return 1;
}
int tot,ok;
void dfs(int x,int y,int s){
	if(ok) return;
	if(s==tot||x==4){
		if(check()) ok=1;
		return;	
	}
	fun(x,y);
	if(y+1<4) dfs(x,y+1,s+1);
	else  dfs(x+1,0,s+1);
	fun(x,y);
	if(y+1<4) dfs(x,y+1,s);
	else  dfs(x+1,0,s); 
}
int main(){
	for(int i=0;i<4;i++)
		for(int j=0;j<4;j++)
			scanf("\n%c",&c),a[i][j]=c=='b'?1:0;
	int ans=inf;
	for(;tot<=16;tot++){
		dfs(0,0,0);
		if(ok){
			printf("%d\n",tot);
			return 0;
		}
	}
	printf("Impossible\n");
 	return 0;
}