• poj 3279


    传送门:http://poj.org/problem?id=3279

    题面描述:

    给你一个方格,这个方格中有M*N个小方块,每个小方块都是0或1,定义一种反转操作:,每次反转范围是中心方块以及其上下左右的方块,反转后状态变化为0->1,1->0。问能不能通过有限次反转操作,将方格的最终状态变为全是0,如果可以,输出一个反转次数最少而且字典序最小的矩阵,矩阵对应的数值为该位置的反转次数,否则,输出IMPOSSIBLE。

    思路:

    1.对于同一个位置来说,最多反转1次,因为只有两种状态,反转两次事实上跟原先状态是一样的。

    2.对于同一个位置,它的最终状态会受其上下左右各个方块反转的影响,这会使问题的分析变得非常复杂,但是我们可以先确定第一行的反转次序,此时对于第一行来说,能够影响它的左中右的反转都已经确定了,那么决定他最终状态的就只有它的下的反转,调节他下面方块的反转次序,使第一行的状态全变成0,然后对于第二行一样,以此类推,到了倒数第一行,此时不仅确定了倒数第二行的状态,也把最后一行的反转次数确定了,同时,最后一行的状态也被确定了(可能有点绕),此时我们只要判断最后一行是不是全是0就可判断这种第一行的反转次序是不是可以满足条件。

    3.接下来,我们来思考如何来枚举第一行的各种反转次数,由1可以知道,每个位置事实上只有0和1两种状态,所以我们可以考虑二进制枚举来解决问题,具体实现在AC代码里面。因为我们是从小到大枚举的,所以最终得到的结果一定是最小字典序的,所以不用再考虑字典序的问题了。

    最终代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn = 20;
    int map[maxn][maxn],flip[maxn][maxn],ans[maxn][maxn],m,n;
    int dx[]  = {1,0,0,0,-1};
    int dy[] = {0,1,0,-1,0};
    int get(int x,int y){
        int c =map[x][y];
        for(int d = 0;d<5;d++){
            int x1 = x+dx[d];
            int y1 = y+dy[d];
            if(x1>=0&&x<m&&y>=0&&y<n){
                c+=flip[x1][y1];
            }
        }
        return c%2;
    }
    int calc(){
        int res = 0;
        for(int i = 1;i<m;i++)
            for(int j = 0;j<n;j++)
            {
                if(get(i-1,j))
                {
                    flip[i][j] = 1;
                }
            }
        for(int i = 0;i<n;i++)
            if(get(m-1,i)!=0)
                return -1;
        for(int i = 0;i<m;i++)
            for(int j = 0;j<n;j++)
                res+=flip[i][j];
        return res;
    }
    int main()
    {
        while(~scanf("%d %d",&m,&n)){
            for(int i = 0;i<m;i++)
                for(int j = 0;j<n;j++)
                    scanf("%d",&map[i][j]);int res = -1;
            for(int i = 0;i< 1<< n;i++){
                
                memset(flip,0,sizeof(flip));
                for(int j = 0;j<n;j++)
                    flip[0][n-j-1] =  i>>j&1;
                int num = calc();
                if(num>=0&&(res<0||res>num)){
                    res = num;
                    memcpy(ans,flip,sizeof(flip));
                }
            }
            if(res==-1)
                printf("IMPOSSIBLE
    ");
            else
            {
                for(int i = 0;i<m;i++)
                    for(int j = 0;j<n;j++)
                        printf("%d%c",ans[i][j],j+1==n?'
    ':' ');
            }
        }
        return 0;
    }

    如还有困惑的地方,请在评论区留言交流!

  • 相关阅读:
    Python单元测试之unittest基础
    linux--硬链接和软链接
    12-8 istio核心功能实战-----可观察性(程访问遥测插件)
    12-7 istio核心功能实战-----可观察性(网络可视化)
    12-6 istio核心功能实战-----可观察性(分布式追踪)
    12-3 部署面向生产的istio-----核心组件
    12 ServiceMesh代表作istio-----12-1 ServiceMes、Istio架构原理
    11-7 Grafana看板和邮件报警
    11-6 监控落地
    11-4 部署前奏-Helm&Operator
  • 原文地址:https://www.cnblogs.com/baihualiaoluan/p/10964444.html
Copyright © 2020-2023  润新知