zoukankan      html  css  js  c++  java
  • POJ 3279 Fliptile【枚举】

    题意:

    又是农夫和牛的故事。。。有m*n个黑白块,黑块的背面是白块,白块背面是黑块,一头牛踩一块,则这个块的上下左右的方块都会转动,问至少踩多少块,才会使所有块都变成白色?

    分析:

    还是开关问题,同样是一个块的转动会影响其他块的状态,但这次不是简单的线性排列,也不能只踩黑块。首先根据字典序,我们可以对第一排从00…00到11..11进行考虑(1表示踩),再后续一排一排的考虑。因为踩一块四周的块都会转动,所以必须规定个踩的原则,发现对于某块来说,他一旦改变上方块的状态,那个块就再也不会改变了,而其他块还有他的下一列改变他的机会(如果存在),所以就以上一行块为原则,如果上方为黑,则踩。最后判断最后一行是否全白。
    字典序,因为他说了是把整个排列当做字符串的字典序,所以肯定是越前面的越小越好,而且从第一个例子中也能看出来。
    -

    代码:

    #include<iostream>
    #include<cstring>
    using namespace std;
    #define mem(s,a)  memset(s,a,sizeof(s));
    int m, n;
    const int maxn = 25, INF = 0x3fffffff;
    int x[5]={-1,0,0,0,1};
    int  y[5] = {0,1,0,-1,0};
    int s[maxn][maxn], a[maxn][maxn], r[maxn][maxn], ans[maxn][maxn];
    int cal()
    {
        int cnt = 0;
        for(int i = 2; i <= m; i++){
            for(int j = 1; j <= n; j++){
                if((a[i-1][j]+r[i-1][j])%2==1) {
                    cnt++;
                    s[i][j] = 1;
                }
                for(int k = 0; k < 5; k++){
                    r[i+x[k]][j+y[k]]+=s[i][j];
                }
            }
        }
       /* for(int i = 1; i <= m; i++){
            for(int j = 1; j <= n; j++){
               cout<<(r[m][i]+ a[m][i])%2;
               if(j!=n)  cout<<' ';
               else cout<<endl;
            }
        }*/
        for(int i =1; i <= n; i++){
            if((r[m][i]+ a[m][i])%2==1) return -1;
        }
    
        return cnt;
    }
    int main (void)
    {
        cin>>m>>n;
        for(int i = 1; i <= m; i++){
            for(int j = 1; j <= n; j++){
                cin>>a[i][j];
            }
        }
        int res = INF;
        for(int i = 0; i <1<<n; i++){
            mem(s,0);mem(r,0);
            int t = 0;
            for(int j =n; j >= 1; j--){
                s[1][j] = i>>j&1;
                for(int k = 0; k < 5; k++){
                    r[1+x[k]][j+y[k]]+=s[1][j];
                }
                t += s[1][j];
            }
           int tm = cal();
           if(tm>=0&&t+tm<res){
                res = t + tm;
                memcpy(ans,s,sizeof(s));
           }
        }
        if(res==INF) {
                cout<<"IMPOSSIBLE"<<endl;
                return 0;
        }
        for(int i = 1; i <= m; i++){
            for(int j = 1; j <= n; j++){
               cout<<ans[i][j];
               if(j!=n)  cout<<' ';
               else cout<<endl;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    go语言基础之安装go开发环境和beego
    mysql之事件的开启和调用
    系统和应用监控指标
    常用的17个运维监控系统(必备知识)
    Kafka Java API操作topic
    Linux安装mysql8.0
    mybatis+Oracle 批量插入数据,有数据做更新操作
    ORACLE数据库导出表,字段名,长度,类型,字段注释,表注释语句
    ORACLE 按时间创建分区表
    oracle创建表空间和用户
  • 原文地址:https://www.cnblogs.com/Tuesdayzz/p/5758807.html
Copyright © 2011-2022 走看看