BZOJ 1647 [Usaco2007 Open]Fliptile 翻格子游戏

原理很简单

只要确定第一行是否翻转就可以确定以后的行是否翻转

但是最后对拍后才过了

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
inline int read(){
    int x=0,f=1,ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline int count(int x){
	int res=0;
	while(x) res+=(x&1),x>>=1;
	return res;
}
int m,n,ans,sum;
int a[16];
inline void pri(int x){
    for(int i=1;i<=n;i++) printf("%d ",x&1),x>>=1;
    puts("");
}
inline bool ok(int x){
    int ex=0,cnt=0;
    for(int i=1;i<=m;i++){
        int b=x;cnt+=count(x);
        x=x^(x<<1)^(x>>1)^a[i]^ex,x%=(1<<n);
        ex=b;
    }
    if(x) return 0;
    if(cnt>=sum) return 0;
    sum=cnt;
    return 1;
}
inline void print(int x){
    int ex=0;
    for(int i=1;i<=m;i++){
        pri(x);int b=x;
        x=x^(x<<1)^(x>>1)^a[i]^ex,x%=(1<<n);
        ex=b;
    }
}
inline int fan(int x){
    int res=0;
    for(int i=1;i<=n;i++) res=(res<<1)+(x&1),x>>=1;
    return res;
}
int main(){
    m=read(),n=read();
    for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++)
            a[i]+=(read()<<(j-1));
    ans=-1;sum=0x3f3f3f3f;
    for(int i=0;i<(1<<n);i++)
        if(ok(fan(i)))
            ans=fan(i);
    if(ans==-1) puts("IMPOSSIBLE");
    else print(ans);
    return 0;
}

  

posted @ 2018-10-26 15:20  古城独钓  阅读(165)  评论(0编辑  收藏  举报