poj 3279 fliptile (翻转棋盘,枚举方法)

思路:

翻转偶数次跟翻转0次是一样的,奇数次是跟1次是一样的,所以最后的结果中只可能有0,1;

下一行的状态可以通过前二行的的状态得到,因为在求(i,j)是否要翻转的时候,(i-1,j)(i-1,j-1)(i-1,j+1)(i-2)(j)是否翻转都已经知道了,并且要(i-1,j)这个位置是0,那么就可以推出(i,j)这个位置是否要翻转,所以其实问题中只要枚举第一行的所有情况,就能推出所有的情况,并且一共最多只有2^15种;

枚举方法要保证最后的答案是字典序最小的,那么可以用二进制来表示每一位的状态(0----2^n),第i种情况下,第j个位置的值应该是i>>j&1(不明白的可以自己推导一下),如果答案是1那么就说明要进行翻转,如果是0,就不用;

代码如下:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define esp 1e-4
using namespace std;
int ini[20][20];
int flip[20][20];
int final_ans[20][20];
int m,n;
int main()
{
	while(cin>>m>>n)
	{
		int ans=1e8;
		int time=0;//要翻转的次数 
		for(int i=1;i<=m;i++)
		{
			for(int j=1;j<=n;j++)
			{
				cin>>ini[i][j];
				
			}
		}
		
		int ok=0;
		for(int i=0;i<(1<>(j-1) &1;
				if(flip[1][j])
					time++;
				
			}
			for(int r=2;r<=m;r++)
			{
				for(int c=1;c<=n;c++)
				{
					if((ini[r-1][c]+flip[r-1][c]+flip[r-1][c-1]+flip[r-1][c+1]+flip[r-2][c])&1)
					{
						flip[r][c]=1;
						time++;
					}
					
					
				}
			}
			int flag=1;
			for(int j=1;j<=n;j++)
			{
				if((ini[m][j]+flip[m][j]+flip[m-1][j]+flip[m][j-1]+flip[m][j+1])&1)
				{
					flag=0;
					break;
				}
				
			}
			if(flag && time

 

你可能感兴趣的:(poj 3279 fliptile (翻转棋盘,枚举方法))