zoukankan      html  css  js  c++  java
  • Luogu 1764 翻转游戏

    题目描述

    kkke在一个n*n的棋盘上进行一个翻转游戏。棋盘的每个格子上都放有一个棋子,每个棋子有2个面,一面是黑色的,另一面是白色的。初始的时候,棋盘上的棋子有的黑色向上,有的白色向上。现在kkke想通过最少次数的翻转,使得棋盘上所有的棋子都是同一个颜色向上的(即全是黑色向上的,或全是白色向上的)。每次翻转的时候,kkke可以选择任意一个棋子,将它翻转,同时,与它上下左右分别相邻的4个棋子也必须同时翻转。

    输入输出格式

    输入格式:

    输入的第一行是一个整数n,表示棋盘是n*n的,

    接下来有n行,每行包括n个字母,表示初始的棋盘状态。如果字母是w,则表示这个棋子当前是白色向上的,如果字母是b,则表示这个棋子当前是黑色向上的。

     

    输出格式:

    输出为一行,如果无法翻转出目标状态,则输出“Impossible”,否则输出一个整数,表示kkke最少需要翻转的次数。

    输入输出样例

    输入样例#1:
    4
    bwwb
    bbwb
    bwwb
    bwww
    
    输出样例#1:
    4

    说明

    【数据范围】

    对于30%的数据,1<=n<=4

    对于100%的数据,1<=n<=16

    题解

      看到这一题, 我试了试 IDA*, 看看能水几分, 没想到只能水30, 果断滚粗。

      直接爆搜显然是会TLE 的, 那么只能考虑其他办法。

      那么我们枚举第一行的翻转, 并把翻转后的图记录, 进行第二行的搜索。

      由于第一行已经不能再翻, 如果第一行存在没有达到目标 颜色的棋子,只能由第二行来翻转。

      所以可以根据第一行的颜色 来 给第二行进行翻转, 并且可能性仅一种。

      这样一直翻转到最后一行结束, 那么除了最后一行 其他棋子 一定达到了目标颜色。

      最后再判断最后一行棋子是否都达到了目标颜色, 如果达到了就更新答案。

    代码

    原谅我丑的不行的代码

     1 #include<cstring>
     2 #include<algorithm>
     3 #include<cstdio>
     4 #define rep(i,a,b) for( int i = (a); i <= (b); ++i )
     5 #define per(i,a,b) for( int i = (a); i >= (b); --i )
     6 using namespace std;
     7 
     8 const int N = 20, inf = ~0U >> 1;
     9 
    10 int n, mp[N][N], ans, tmp[N][N];
    11 char s[N];
    12 
    13 int cal( int x , int pos ) {
    14     return (x >> pos) & 1; 
    15 }
    16 
    17 int work( int re , int col) {
    18     rep( i, 1, n - 1 ) rep( j, 0, n - 1 ) if( tmp[i - 1][j] != col ){
    19         re++;
    20         tmp[i][j] ^= 1;
    21         tmp[i + 1][j] ^= 1;
    22         if(j) tmp[i][j - 1] ^= 1;
    23         if(j != n - 1) tmp[i][j + 1] ^= 1;
    24     }
    25     rep( j, 0, n - 1 ) if( tmp[n - 1][j] != col ) return inf;
    26     return re;
    27 }
    28 
    29 int dfs() {
    30     int re = inf;
    31     rep( i, 0, (1 << n) - 1 ) rep( col, 0, 1){
    32         rep( j, 0, n - 1 ) rep( k, 0, n - 1 ) tmp[j][k] = mp[j][k];
    33         int cnt = 0;
    34         rep( j, 0, n - 1 ) if( cal( i, j ) ) cnt++;
    35         rep( j, 0, n - 1 ) if( cal( i, j ) ^ cal( i , j - 1 ) ^ cal( i, j + 1 ) ) tmp[0][j] ^= 1;
    36         rep( j, 0, n - 1 ) if( cal( i, j ) ) tmp[1][j] ^= 1;
    37         re = min( re, work(cnt, col) );
    38     }
    39     return re;
    40 }
    41 
    42 int main()
    43 {
    44     scanf("%d",&n);
    45     rep( i, 0, n - 1 ) {
    46         scanf("%s",s);
    47         rep( j, 0, n - 1 ) mp[i][j] = s[j] == 'w';
    48     }
    49     ans = dfs();
    50     if( ans == inf ) printf("Impossible
    ");
    51     else printf("%d
    ", ans);
    52 }
    View Code
  • 相关阅读:
    fzuoj Problem 2177 ytaaa
    zoj The 12th Zhejiang Provincial Collegiate Programming Contest Capture the Flag
    zoj The 12th Zhejiang Provincial Collegiate Programming Contest Team Formation
    zoj The 12th Zhejiang Provincial Collegiate Programming Contest Beauty of Array
    zoj The 12th Zhejiang Provincial Collegiate Programming Contest Lunch Time
    zoj The 12th Zhejiang Provincial Collegiate Programming Contest Convert QWERTY to Dvorak
    zoj The 12th Zhejiang Provincial Collegiate Programming Contest May Day Holiday
    zoj The 12th Zhejiang Provincial Collegiate Programming Contest Demacia of the Ancients
    zjuoj The 12th Zhejiang Provincial Collegiate Programming Contest Ace of Aces
    csuoj 1335: 高桥和低桥
  • 原文地址:https://www.cnblogs.com/cychester/p/9478616.html
Copyright © 2011-2022 走看看