zoukankan      html  css  js  c++  java
  • POJ 3279 Fliptile (搜索)

    POJ 3279 Fliptile

    题意

    关灯问题,求最小的操作次数,并给出操作方式。
    

    传送门

    思路

    注意到该问题有如下性质:
    一旦第一行的操作状态确定后,其它所有的状态也就随之确定了。具体而言:
    如果map[i][j]==1,那么为了把它变成0,我们只需要对flip[i+1][j]
    进行一次操作,记录之。如此下去,
    在最后一定可以把row-1行全部变成0.
    所以再在最后判断一下最后一个row是不是全部是0就好了。
    最后输出flip数组(ans)。
    

    第一row的求法:详见代码

    代码

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int maxn=16,maxm=16,inf=1e9;
    int a[maxn][maxm],flip[maxn][maxm],ans[maxn][maxm];
    int col,row;
    int ok(int x,int y){
        if(x<0||x>=row||y<0||y>=col)return 0;
        return 1;
    }
    int xx[5]={0,0,1,-1,0};
    int yy[5]={1,-1,0,0,0};
    int check(int x,int y){
        int cnt=a[x][y];
        for(int i=0;i<5;i++){
            int nx=x+xx[i];
            int ny=y+yy[i];
            if(ok(nx,ny))cnt+=flip[nx][ny];
        }
        return cnt&1;
    }
    int calc(){
        for(int i=1;i<row;i++){
            for(int j=0;j<col;j++){
                if(check(i-1,j))
                    flip[i][j]++;
            }
        }
        for(int i=0;i<col;i++)
            if(check(row-1,i))return 0;
        int cnt=0;
        for(int i=0;i<row;i++)
            for(int j=0;j<col;j++)
                if(flip[i][j])cnt++;
        return cnt;
    }
    int main(){
    //  freopen("DDD.in","r",stdin);
        scanf("%d%d",&row,&col);
        for(int i=0;i<row;i++)
            for(int j=0;j<col;j++)
                scanf("%d",&a[i][j]);
    
        /*for(int i=0;i<row;i++){
            for(int j=0;j<col;j++)
                printf("%d",a[i][j]);
            printf("
    ");
        }*/
    
        int cnt=inf;
        for(int i=0;i<(1<<col);i++){//枚举从000...00到111...11
            memset(flip,0,sizeof flip);
            for(int j=0;j<col;j++){
                flip[0][col-j-1]=(i>>j)&1;//分离每一个状态
            }
            int num=calc();
            if(num<cnt&&num!=0){
                cnt=num;
                memcpy(ans,flip,sizeof flip);
            }
        }
        if(cnt==inf)printf("IMPOSSIBLE
    ");
        else{
            for(int i=0;i<row;i++){
                printf("%d",ans[i][0]);
                for(int j=1;j<col;j++)
                    printf(" %d",ans[i][j]);
                printf("
    ");
            }
        }
        return 0;
    }

    后记

    正确性何证?
    一开始的对状态进行的搜索可以用位运算完成。
    
  • 相关阅读:
    库函数文件操作
    系统文件操作函数
    time函数
    字符(串)输入输出函数
    select&epoll
    epoll
    select
    Apache 配置虚拟主机三种方式
    Apache VirtualHost配置
    Scrapy中用xpath/css爬取豆瓣电影Top250:解决403HTTP status code is not handled or not allowed
  • 原文地址:https://www.cnblogs.com/yohanlong/p/6058149.html
Copyright © 2011-2022 走看看