• POJ 3279 Fliptile(DFS+反转)


    题目链接:http://poj.org/problem?id=3279

    题目大意:有一个n*m的格子,每个格子都有黑白两面(0表示白色,1表示黑色)。我们需要把所有的格子都反转成黑色,每反转一个格子,它上下左右的格子都会跟着反转。请求出用最小步数完成反转时每个格子反转的次数。有多个解时,输出字典序最小的一组。

    解题思路:只要枚举第一行的2^m种情况,如果一个位置上一行是1,那这个位置一定要反转,因为只有这一行能改变上一行,所以每一行的状态都是由前一行决定的。只要最后判断最后一行是不是都是0即可,关于最小字典序,只要从右往左枚举,第一个方案就是正解。(时间复杂度O(n*m*2^m)。

    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 const int N=20;
     5 
     6 int n,m;
     7 bool flag;
     8 int map[N][N],sta[N][N],tmp[N][N];//sta表示踩或不踩
     9 int d[5][2]={{0,1},{1,0},{0,0},{0,-1},{-1,0}};
    10 
    11 
    12 //反转坐标为(i,j)的格子 
    13 void reverse(int i,int j,int s[][N]){
    14     for(int k=0;k<5;k++){
    15         int x=i+d[k][0];
    16         int y=j+d[k][1];
    17         s[x][y]=!s[x][y];
    18     }
    19 }
    20 
    21 void dfs(int y){
    22     if(flag)
    23         return;
    24     if(y>=1){ 
    25         //不踩 
    26         sta[1][y]=0;        
    27         dfs(y-1);
    28         //
    29         sta[1][y]=1;
    30         reverse(1,y,map);
    31         dfs(y-1);
    32         reverse(1,y,map);
    33     }
    34     else{
    35         for(int i=1;i<=n;i++){
    36             for(int j=1;j<=m;j++){
    37                 tmp[i][j]=map[i][j];
    38             }
    39         }
    40         for(int i=2;i<=n;i++){
    41             for(int j=1;j<=m;j++){
    42                 sta[i][j]=0;
    43                 if(tmp[i-1][j]==1){
    44                     reverse(i,j,tmp);
    45                     sta[i][j]=1;
    46                 }
    47             }
    48         }
    49         
    50         bool sign=true;
    51         for(int i=1;i<=m;i++){
    52             if(tmp[n][i]==1){
    53                 sign=false;
    54                 break;
    55             }
    56         }
    57         if(sign){
    58             flag=true;
    59             for(int i=1;i<=n;i++){
    60                 for(int j=1;j<=m;j++){
    61                     if(j==m)
    62                         printf("%d
    ",sta[i][j]);
    63                     else
    64                         printf("%d ",sta[i][j]);
    65                 }
    66             }
    67         }
    68     }
    69 }
    70 
    71 int main(){
    72     while(~scanf("%d%d",&n,&m)){
    73         memset(sta,0,sizeof(sta));
    74         flag=false;
    75         for(int i=1;i<=n;i++){
    76             for(int j=1;j<=m;j++){
    77                 scanf("%d",&map[i][j]);
    78             }
    79         }
    80         dfs(m);
    81         if(!flag)
    82             puts("IMPOSSIBLE");
    83     }
    84     return 0;
    85 }
  • 相关阅读:
    C#搭建Oauth2.0认证流程以及代码示例
    DirectoryEntry配置IIS7出现ADSI Error:未知错误(0x80005000)
    C# 操作IIS方法集合
    dedecms首页入口的详细注释
    分享几个在线生成网址二维码的API接口
    Windows平台分布式架构实践
    WINDOWS 2008Server 配置nginx 反向代理服务器 安装成服务
    [支付宝]手机网站支付快速接入
    支付宝 app支付 沙盘使用
    支付宝接口开发-手机网站支付-沙箱测试
  • 原文地址:https://www.cnblogs.com/fu3638/p/7512656.html
Copyright © 2020-2023  润新知