zoukankan      html  css  js  c++  java
  • 1815:画家问题

    题目链接:

    NOI题库: http://noi.openjudge.cn/ch0201/1815/

    poj 1681: http://poj.org/problem?id=1681

    总时间限制: 1000ms内存限制: 65536kB
    描述

    有一个正方形的墙,由N*N个正方形的砖组成,其中一些砖是白色的,另外一些砖是黄色的。Bob是个画家,想把全部的砖都涂成黄色。但他的画笔不好使。当他用画笔涂画第(i, j)个位置的砖时, 位置(i-1, j)、 (i+1, j)、 (i, j-1)、 (i, j+1)上的砖都会改变颜色。请你帮助Bob计算出最少需要涂画多少块砖,才能使所有砖的颜色都变成黄色。

    输入第一行是一个整数n (1≤n ≤15),表示墙的大小。接下来的n行表示墙的初始状态。每一行包含n个字符。第i行的第j个字符表示位于位置(i,j)上的砖的颜色。“w”表示白砖,“y”表示黄砖。输出一行,如果Bob能够将所有的砖都涂成黄色,则输出最少需要涂画的砖数,否则输出“inf”。样例输入

    5
    wwwww
    wwwww
    wwwww
    wwwww
    wwwww

    样例输出

    15 

    算法分析:

    这个题目有些像熄灯问题,解法也是利用了熄灯问题中第一行的选择决定下一行的选择。所以只需要枚举出第一行所有的操作方案,以及验证最后一行是否正确。

    大体思路:枚举第一行的所有可能的操作方案。对每一个方案都要统计一下该方案需要涂的方块数目并检验该方案能否使得所有的方块最后都变为黄色。检验方法就是扫描最后一行是否剩余白色块即可。

    代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<limits.h>
     4 
     5 int n;
     6 char src[18][18],temp1[18][18];
     7 int dx[4]={-1,0,1,0};//上右下左 
     8 int dy[4]={0,1,0,-1};
     9 
    10 int GetBit(int c,int i)//取c的第i位。i从0开始。 
    11 {  return ( c >> i ) & 1;  }
    12 void Flip(int i,int j)//将src[i][j]及其周围元素取反 
    13 {
    14     int k,x,y;
    15     src[i][j]=src[i][j]=='w'?'y':'w';
    16     for(k=0;k<4;k++)
    17     {
    18         x=i+dx[k];
    19         y=j+dy[k];
    20         if(x>=0&&x<n&&y>=0&&y<n)
    21         {
    22             src[x][y]=src[x][y]=='w'?'y':'w';
    23         }
    24     }
    25 }
    26 int main(int argc, char *argv[])
    27 {
    28     int i,j,k,t;
    29     char str[20];
    30     int count,min=INT_MAX;
    31 
    32     scanf("%d",&n);
    33     for(i=0;i<n;i++)
    34     {
    35         scanf("%s",str);
    36         for(j=0;j<n;j++)
    37         {
    38             temp1[i][j]=src[i][j]=str[j];
    39         }
    40     }
    41     
    42     t=(1<<n);//第0行总共有2^n种不同的涂法 
    43     for(i=0;i<=t;i++)//枚举所有涂法,对每一种涂法都统计该方案需要涂的数量并检验该方案能否全变为y。 
    44     {
    45         memcpy(src,temp1,sizeof(src));
    46         /*for(k=0;k<n;k++)
    47             for(j=0;j<n;j++)
    48                 src[k][j]=temp1[k][j];*/
    49         count=0;
    50         
    51         for(j=0;j<n;j++)//根据当前方案i各个比特的值去涂第0行 
    52         {
    53             if(GetBit(i,j)==1)//获取i的第j个比特。若为1,则需要涂(0,j)位置 
    54             {
    55                 Flip(0,j);
    56                 count++;
    57             } 
    58         }
    59         for(k=1;k<n;k++)//扫描除了第0行以外的所有行 
    60         {
    61             for(j=0;j<n;j++)
    62             {
    63                 if(src[k-1][j]=='w')
    64                 {
    65                     Flip(k,j);
    66                     count++;
    67                 }
    68             }
    69         }
    70         for(j=0;j<n;j++)//扫描最后一行检查是否有未变为y的单元 
    71         {
    72             if(src[n-1][j]=='w') break;
    73         }
    74         if(j==n&&count<min) min=count;
    75     }
    76     if(min==INT_MAX) printf("inf
    ");
    77     else printf("%d
    ",min);
    78     return 0;
    79 }

    poj提交的代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<limits.h>
     4 
     5 int n;
     6 char src[18][18],temp1[18][18];
     7 int dx[4]={-1,0,1,0};//上右下左 
     8 int dy[4]={0,1,0,-1};
     9 
    10 int GetBit(int c,int i)//取c的第i位。i从0开始。 
    11 {  return ( c >> i ) & 1;  }
    12 void Flip(int i,int j)//将src[i][j]及其周围元素取反 
    13 {
    14     int k,x,y;
    15     src[i][j]=src[i][j]=='w'?'y':'w';
    16     for(k=0;k<4;k++)
    17     {
    18         x=i+dx[k];
    19         y=j+dy[k];
    20         if(x>=0&&x<n&&y>=0&&y<n)
    21         {
    22             src[x][y]=src[x][y]=='w'?'y':'w';
    23         }
    24     }
    25 }
    26 int main(int argc, char *argv[])
    27 {
    28     int i,j,k,t;
    29     char str[20];
    30     int count,min=INT_MAX;
    31 
    32     int T;
    33     scanf("%d",&T);
    34     for(;T>0;T--)
    35     {
    36         min=INT_MAX;
    37         scanf("%d",&n);
    38         for(i=0;i<n;i++)
    39         {
    40             scanf("%s",str);
    41             for(j=0;j<n;j++)
    42             {
    43                 temp1[i][j]=src[i][j]=str[j];
    44             }
    45         }
    46         
    47         t=(1<<n);//第0行总共有2^n种不同的涂法 
    48         for(i=0;i<=t;i++)//枚举所有涂法,对每一种涂法都统计该方案需要涂的数量并检验该方案能否全变为y。 
    49         {
    50             memcpy(src,temp1,sizeof(src));
    51             /*for(k=0;k<n;k++)
    52                 for(j=0;j<n;j++)
    53                     src[k][j]=temp1[k][j];*/
    54             count=0;
    55             
    56             for(j=0;j<n;j++)//根据当前方案i各个比特的值去涂第0行 
    57             {
    58                 if(GetBit(i,j)==1)//获取i的第j个比特。若为1,则需要涂(0,j)位置 
    59                 {
    60                     Flip(0,j);
    61                     count++;
    62                 } 
    63             }
    64             for(k=1;k<n;k++)//扫描除了第0行以外的所有行 
    65             {
    66                 for(j=0;j<n;j++)
    67                 {
    68                     if(src[k-1][j]=='w')
    69                     {
    70                         Flip(k,j);
    71                         count++;
    72                     }
    73                 }
    74             }
    75             for(j=0;j<n;j++)//扫描最后一行检查是否有未变为y的单元 
    76             {
    77                 if(src[n-1][j]=='w') break;
    78             }
    79             if(j==n&&count<min) min=count;
    80         }
    81         if(min==INT_MAX) printf("inf
    ");
    82         else printf("%d
    ",min);
    83     }
    84     return 0;
    85 }
    View Code
  • 相关阅读:
    vue中$refs、$slot、$nextTick相关的语法
    js中hash、hashchange事件
    js中filter的用法
    ES6新特性-函数的简写(箭头函数)
    js中把ajax获取的数据转化成树状结构(并做成多级联动效果)
    jq中get()和eq()的区别
    new Date() 日期格式处理
    微信小程序 加载图片时,先拉长,再恢复正常
    一个例子理解ES6的yield关键字
    eclipse在光标停留在同一对象的背景色提示,开启与关闭
  • 原文地址:https://www.cnblogs.com/huashanqingzhu/p/7285999.html
Copyright © 2011-2022 走看看