HDU 1882 Strange Billboard

  状态压缩,我们枚举第一行的所有状态,然后根据第一行去转变下面的行,枚举或者深搜直到最后最后一行,可以判断是不是所有的1都可以全部转换为0,记录所有的解,输出最小的一个就可以.

这里有一个很重要的优化,就是当n比m大的,转置这个矩阵,如果不加这个在G++的情况下会超时,C++900Ms多AC.代码及注释如下

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f
int row[20],newrow[20],n,m;
int dfs(int id,int prerow,int tot)
{
    if(id == n)
    {
        if(prerow != 0)return inf;
        else return tot;
    }
    int now = newrow[id];///这是当前行
    for(int j = 0; j < m; j++)
        if(prerow & (1<<j))///now(当前行)受prerow(前一行)的限制,只有prenow的这一列也是X的时候才可以反转
        {
            tot++;
            now ^= 1<<j;
            if(j > 0)now ^= 1<<(j-1);
            if(j < m-1)now ^= 1<<(j+1);
            if(id+1 < n)newrow[id+1] ^= 1<<(j);///当前行的下一行
        }
    dfs(id+1,now,tot);
}
int main()
{
    char maps[20][20];
    while(~scanf("%d%d",&n,&m))
    {
        if(n == 0 && m == 0) return 0;
        for(int i = 0; i < n; i++)
            scanf("%s",maps[i]);
        if(n >= m)
        {
            for(int i = 0; i < n; i++)
            {
                row[i] = 0;
                for(int j = 0; j < m; j++)
                    if(maps[i][j] == ‘X‘)
                        row[i] |= (1<<j);
            }
        }
        else///转置优化
        {
            for(int i = 0; i < m; i++)
            {
                row[i] = 0;
                for(int j = 0; j < n; j++)
                    if(maps[j][i] == ‘X‘)
                        row[i] |= (1<<j);
            }
            swap(n,m);
        }
        int ans = inf,tot;
        for(int i=0; i<(1<<m); i++)///枚举第一行的所有状态
        {
            tot = 0;
            for(int j = 0; j < n; j++)
                newrow[j] = row[j];
            for(int j=0; (1<<j)<=i; j++)
                if(i & (1<<j))///如果是X就反转,并且带动周围4个点,边界需要特判
                {
                    tot++;
                    newrow[0] ^= (1<<j);
                    if(j > 0)newrow[0] ^= (1<<(j-1));
                    if(j < m-1)newrow[0] ^= (1<<(j+1));
                    if(n > 1) newrow[1] ^= (1<<j);
                }
            tot = dfs(1,newrow[0],tot);///开始搜索到最后一行
            if(tot < ans)ans = tot;
        }
        if(ans == inf)printf("Damaged billboard.\n");
        else printf("You have to tap %d tiles.\n",ans);
    }
    return 0;
}
时间: 2024-10-29 08:59:31

HDU 1882 Strange Billboard的相关文章

hdu 1882 Strange Billboard(位运算+枚举)

http://acm.hdu.edu.cn/showproblem.php?pid=1882 感觉非常不错的一道题. 给一个n*m(1<=n,m<=16)的矩阵,每一个格子都有黑白两面,当翻一个格子时,它的上下左右都要翻转,问最后使格子全变为白色的最少翻转步数. 仅仅需枚举第一行的状态即可,由于对于第i(i>=2)行j列翻转情况受上一行的制约,仅仅有当上一行也是'X'的时候,该行j列才干翻转,使i-1行j列变为'.',否则i行j列不能翻转.依次进行下去,当最后一行全变为白色,说明翻转成功

HDU 1882 Strange Billboard(位运算)

题目链接 题意 : 给你一个矩阵,有黑有白,翻转一个块可以让上下左右都翻转过来,问最少翻转多少次能让矩阵变为全白. 思路 : 我们从第一行开始枚举要翻转的状态,最多可以枚举到2的16次方,因为你只要第一行的确定了,第二行要翻转的也就确定了,所以第一行的状态决定了最后的状态.看了网上大神,真是让位运算废了啊,,,,,太复杂了...... 1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #

hdu 2899 Strange fuction (二分)

题目链接:http://acm.hdu.edu.cn/showproblem.pihp?pid=2899 题目大意:找出满足F(x) = 6 * x^7+8*x^6+7*x^3+5*x^2-y*x (0 <= x <=100)的x值.注意精确度的问题. 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 using namespace std; 5 double y; 6 7 doub

HDU 2795:Billboard(线段树)

http://acm.hdu.edu.cn/showproblem.php?pid=2795 Billboard Problem Description At the entrance to the university, there is a huge rectangular billboard of size h*w (h is its height and w is its width). The board is the place where all possible announce

杭电 HDU ACM 2795 Billboard(线段树伪装版)

Billboard Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 14144    Accepted Submission(s): 6058 Problem Description At the entrance to the university, there is a huge rectangular billboard of

ACM : HDU 2899 Strange fuction 解题报告 -二分、三分

Strange fuction Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5933 Accepted Submission(s): 4194 Problem Description Now, here is a fuction: F(x) = 6 * x^7+8*x^6+7*x^3+5*x^2-y*x (0 <= x <=100) C

HDU 2899 Strange fuction

Strange fuction Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5253    Accepted Submission(s): 3750 Problem Description Now, here is a fuction:  F(x) = 6 * x^7+8*x^6+7*x^3+5*x^2-y*x (0 <= x <=

Hdu 2899 - Strange fuction 二分/三分求函数极值点

Strange fuction Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4527    Accepted Submission(s): 3251 Problem Description Now, here is a fuction: F(x) = 6 * x^7+8*x^6+7*x^3+5*x^2-y*x (0 <= x <=

HDU - 5198 - Strange Class &amp;&amp; 5199 - Gunner

Strange Class Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 74    Accepted Submission(s): 60 Problem Description In Vivid's school, there is a strange class(SC). In SC, the students' names ar