Fliptile POJ - 3279 (Status Compression, Search)

Fliptile

Title link: POJ - 3279
title meaning: M*N grid, the side length of each small grid is unit length 1, 0 means the grid is white, 1 means black, each time flipping a grid can make itself and the four surrounding The grid changes from 1 to 0, or from 0 to 1; finally, all grids are white, that is, they are all 0;
each grid is flipped at most once, if it is flipped twice, it will return to the previous state, so there should be 2 ^(n*m) modes of operation; m and n range from 1 to 15, so if you search directly, , 2^225, will you go to the next big bang? ? ?
Another way of thinking, for the first row, there are 2^n operations. After processing the first row, look at the next row. If the corresponding position of the previous row of this row is 1, then this position must be flipped, because at this time the upper row A line has been processed, and only the position flip can change the corresponding position of the previous line, and process them in sequence until the end of the last line;
after judging whether the last line has been all 0 (at this time, each line above has been processed, and no There will be 1), if so, then this is a feasible operation, record it, and finally output the smallest number of operations;

#include <cstdio>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
int G[20][20], ans, m, n, f[20][20], p[20][20], q[20][20];
void flip(int i, int j){//Flip i, j position, itself and the surrounding squares are flipped at the same time;
	f[i][j]=!f[i][j];
	if(i+1<=m)
		f[i+1][j]=!f[i+1][j];
	if(i-1>0)
		f[i-1][j]=!f[i-1][j];
	if(j+1<=n)
		f[i][j+1]=!f[i][j+1];
	if(j-1>0)
		f[i][j-1]=!f[i][j-1];
}
int Count(int k){//When the operation state of the first line is k, the number of operations that have been performed;
	int cnt=0;
	while(k){
		cnt+=k&1;
		k>>=1;
	}
	return cnt;
}
int main(){
	scanf("%d%d", &m, &n);
	for(int i=1; i<=m; i++){
		for(int j=1; j<=n; j++){
			scanf("%d", &G[i][j]);
		}
	}
	int res=0, w=(1<<n);
	ans=INF;
	for(int k=0; k<w; k++){
		res=Count(k);
		memset(q, 0, sizeof(q));
		for(int i=1; i<=m; i++){
			for(int j=1; j<=n; j++){
				f[i][j]=G[i][j];
			}
		}
		for(int j=1; j<=n; j++){
			if((1<<(j-1))&k){//Whether the corresponding position is flipped;
				flip(1, j);
				q[1][j]=1;
			}
		}
		for(int i=2; i<=m; i++){
			for(int j=1; j<=n; j++){
				if(f[i-1][j]){
					flip(i, j);
					q[i][j]=1;
					res++;
				}
			}
		}
		int flag=0;
		for(int j=1; j<=n; j++){
			if(f[m][j]){
				flag=1;
				break;
			}
		}
		if(flag) continue;
		if(res<ans){
			ans=res;
			for(int i=1; i<=m; i++){
				for(int j=1; j<=n; j++){
					p[i][j]=q[i][j];
				}
			}
		}
	}
	if(ans>=INF) printf("IMPOSSIBLE\n");
	else
	for(int i=1; i<=m; i++){
		for(int j=1; j<=n; j++){
			printf("%d%c", p[i][j], j==n?'\n':' ');
		}
	}
	return 0;
}



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325782680&siteId=291194637