UVALive 3953 Strange Billboard (状态压缩+枚举)

Strange Billboard

题目链接:

http://acm.hust.edu.cn/vjudge/contest/129733#problem/A

Description


The marketing and public-relations department of the Czech Technical University has designed a new reconfigurable mechanical Flip-Flop Bill-Board (FFBB). The billboard is a regular twodimensional grid of R×C square tiles made of plastic. Each plastic tile is white on one side and black on the other. The idea of the billboard is that you can create various pictures by flipping individual tiles over. Such billboards will hang above all entrances to the university and will be used to display simple pictures and advertise upcoming academic events.
To change pictures, each billboard is equipped with a "reconfiguration device". The device is just an ordinary long wooden stick that is used to tap the tiles. If you tap a tile, it flips over to the other side, i.e., it changes from white to black or vice versa. Do you agree this idea is very clever?
Unfortunately, the billboard makers did not realize one thing. The tiles are very close to each other and their sides touch. Whenever a tile is tapped, it takes all neighboring tiles with it and all of them flip over together. Therefore, if you want to change the color of a tile, all neighboring tiles change their color too. Neighboring tiles are those that touch each other with the whole side. All inner tiles have 4 neighbors, which means 5 tiles are flipped over when tapped. Border tiles have less neighbors, of course.
For example, if you have the billboard configuration shown in the left picture above and tap the tile marked with the cross, you will get the picture on the right. As you can see, the billboard reconfiguration is not so easy under these conditions. Your task is to find the fastest way to ``clear" the billboard, i.e., to flip all tiles to their white side.

Input


The input consists of several billboard descriptions. Each description begins with a line containing two integer numbers R and C (1 <= R, C <= 16) specifying the billboard size. Then there are R lines, each containing C characters. The characters can be either an uppercase letter "X" (black) or a dot "." (white). There is one empty line after each map. The input is terminated by two zeros in place of the board size.

Output


For each billboard, print one line containing the sentence "You have to tap T tiles.", where T is the minimal possible number of taps needed to make all squares white. If the situation cannot be solved, output the string "Damaged billboard." instead.

Sample Input

5 5 
XX.XX 
X.X.X 
.XXX. 
X.X.X 
XX.XX 

5 5 
.XX.X 
..... 
..XXX 
..X.X 
..X.. 

1 5 
...XX 

5 5 
...X. 
...XX 
.XX.. 
..X.. 
..... 

8 9 
..XXXXX.. 
.X.....X. 
X..X.X..X 
X.......X 
X.X...X.X 
X..XXX..X 
.X.....X. 
..XXXXX.. 

0 0

Sample Output

You have to tap 5 tiles. 
Damaged billboard. 
You have to tap 1 tiles. 
You have to tap 2 tiles. 
You have to tap 25 tiles.

Source


2016-HUST-线下组队赛-2


题意:


在有n*m个格子的游戏盘上有若干黑白方块,每次可以选取任一格子反转其颜色,但是同时会导致其周围四个格子也被翻转.
求用最少的操作使得所有的格子变白.


题解:


考虑最少操作:当第一行确定后,第二行我们翻转其上方还有黑色的格子,这样可以保证第一行全白. 依次进行,如果最后一行操作后后全白,那就是一种可行操作.
所以只需要枚举第一行的状态即可,枚举量在 2^16 以内.
这里枚举翻转情况比枚举结果状态要好. (每个位置要么翻要么不翻,不可能翻两次--等于没翻).
用状态压缩来处理起来还是蛮方便的. 不过这种做法的耗时在1500ms上下.(过不了HDU-1882)
看了一些耗时较少的代码(100ms内),大多是用高斯消元做的.


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <vector>
#include <list>
#define LL long long
#define eps 1e-8
#define maxn 20
#define mod 100000007
#define inf 0x3f3f3f3f
#define mid(a,b) ((a+b)>>1)
#define IN freopen("in.txt","r",stdin);
using namespace std;

typedef pair<int,int> pii;
int n,m;
int init_state[maxn];
int state[maxn];

bool is_ok(int x, int y) {
    return x>=0 && y>=0 && x<n && y<m;
}

void flip(int x, int y) {
    if(is_ok(x, y)) state[x] ^= 1 << y;
    if(is_ok(x+1, y)) state[x+1] ^= 1 << y;
    if(is_ok(x-1, y)) state[x-1] ^= 1 << y;
    if(is_ok(x, y+1)) state[x] ^= 1 << (y+1);
    if(is_ok(x, y-1)) state[x] ^= 1 << (y-1);
}


int solve() {
    int ans = inf;
    for(int s=0; s<(1<<m); s++) { //枚举第一行的翻转情况 (这里不要枚举结果状态)
        int cnt = 0;
        for(int i=0; i<n; i++) state[i] = init_state[i];
        for(int i=0; i<m; i++) if(s & (1<<i)) {
            flip(0, i); cnt++;
        }

        for(int i=1; i<n; i++) {
            for(int j=0; j<m; j++) if(state[i-1] & (1<<j)){
                flip(i, j); cnt++;
            }
            if(cnt >= ans) break;
        }

        if(!state[n-1]) ans = min(ans, cnt);
    }

    return ans;
}

int main(int argc, char const *argv[])
{
    //IN;

    while(scanf("%d %d", &n,&m) != EOF && (n||m))
    {
        for(int i=0; i<n; i++) {
            char str[maxn];
            scanf("%s", str);
            init_state[i] = 0;
            for(int j=0; j<m; j++) if(str[j] == 'X')
                init_state[i] |= 1 << j;
        }

        int ans = solve();
        if(ans == inf) printf("Damaged billboard.\n");
        else printf("You have to tap %d tiles.\n", ans);
    }

    return 0;
}

转载于:https://www.cnblogs.com/Sunshine-tcf/p/5798894.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值