HDU 4012 Paint on a Wall(BFS+位压缩)(好题)

题意:这题的意思有一个2*n的矩形,要给这个矩形涂色每次可以涂一个矩形形状的某种颜色,允许新颜色覆盖旧的颜色求最少多少步可以求出。(1<=n<=8)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4012

准备拿这题学位压缩,结果看不懂题解...,然后一气之下去学状压dp...才看懂了什么是位压缩,才看懂了这题的题解,然后自己码出来了,一题好题就这么被我水掉了...

思路:每次涂色以后必有一个格子的颜色是最终的颜色,否则这次涂色根本没意义,所以我们把每次涂色后哪些格子成为最终颜色的所有可能都入队,入队的元素是一个struct包含步数和最终颜色已确定的木块集合,这个集合必须用整数表示,所以用到状态压缩,因为最多只有16个格子,所以用16位的二进制来表示,1,表示此格子已是最终颜色,0,表示仍待涂色。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<queue>
using namespace std;
struct node
{
    int step,cur;
};
int len;
bool flag[1<<16]; //  记录哪些格子已是最终颜色
char str[20];
int bfs()
{
    memset(flag,0,sizeof(flag));
    queue<node>que;
    node start={0,0};
    que.push(start);
    flag[0]=true;
    while(!que.empty()){
        node now=que.front();
        que.pop();
        if(now.cur==(1<<2*len)-1) return now.step; //颜色已涂满所有格子
        node next;
        next.step=now.step+1;
        for(int i=0;i<2*len;i++){  //遍历这个图,找个起点开始涂色
            int tmp=0;
            if((1<<i)&now.cur) continue; //这个点已是最终颜色,continue
            for(int j=i;j<(i/len+1)*len;j++){  //单行向右扩展,上界的确定是技巧
                if((1<<j)&now.cur) break;       //已扩展到最终颜色,不能把它覆盖,扩展结束
                if(str[j]==str[i]) tmp|=(1<<j); //如果拓展的位置需涂的颜色和起点颜色一样,那么就涂
            }
            for(int j=i-1;j>=(i/len)*len;j--){ //单行向左扩展,下界的确定是技巧
                if((1<<j)&now.cur) break;   //已扩展到最终颜色,不能把它覆盖,扩展结束
                if(str[j]==str[i]) tmp|=(1<<j);//如果拓展的位置需涂的颜色和起点颜色一样,那么就涂
            }
            for(int j=tmp;j;j=tmp&(j-1)){
    //把本次单行扩展的所有格子最终哪些格子成为最终颜色的所有可能入队,所有
    //可能也就是子集的所有可能,这种遍历集合子集的方式属于位压缩的知识
                if(!flag[j|now.cur]){  //这种情况已经产生过就不需入队了
                    flag[j|now.cur]=1;
                    next.cur=(j|now.cur);
                    que.push(next);
                }
            }
            if(i>=len) continue;  //双行扩展,只要对某一行的点遍历作为起点即可
            if((1<<(i+len))&now.cur) continue; //易错,这个起点的另一行对应的起点如果已是最终颜色,continue
            tmp=0;
            for(int j=i;j<len;j++){  //和单行拓展类似
                if((1<<j)&now.cur)break;
                if((1<<(j+len))&now.cur)break;
                if(str[j]==str[i]) tmp|=(1<<j);
                if(str[j+len]==str[i]) tmp|=(1<<(j+len));
            }
            for(int j=i-1;j>=0;j--){
                if((1<<j)&now.cur) break;
                if((1<<(j+len))&now.cur) break;
                if(str[j]==str[i])tmp|=(1<<j);
                if(str[j+len]==str[i]) tmp|=(1<<(j+len));
            }
            for(int j=tmp;j;j=(j-1)&tmp){ //和单行拓展子集入队类似
                if(!flag[j|now.cur ]){
                    flag[j|now.cur ]=1;
                    next.cur=(j|now.cur);
                    que.push(next);
                }
            }
        }
    }
}
int main()
{
    int _,cnt=0;
    scanf("%d",&_);
    while(_--){
        scanf("%d",&len);
        scanf("%s%s",str,str+len);
        printf("Case #%d: %d\n",++cnt,bfs());
    }
    return 0;
}
时间: 2024-09-27 17:27:16

HDU 4012 Paint on a Wall(BFS+位压缩)(好题)的相关文章

HDU 4012 Paint on a Wall (状态压缩+BFS)

Paint on a Wall Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total Submission(s): 824    Accepted Submission(s): 321 Problem Description Annie wants to paint her wall to an expected pattern. The wall can be rep

HDU 4012 Paint on a Wall(状压+bfs)

Paint on a Wall Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)Total Submission(s): 830    Accepted Submission(s): 325 Problem Description Annie wants to paint her wall to an expected pattern. The wall can be repr

hdu 1429 胜利大逃亡(续)(bfs+位压缩)

胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7346    Accepted Submission(s): 2546 Problem Description Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)…… 这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带

hdu - 1429 胜利大逃亡(续) (bfs状态压缩)

http://acm.hdu.edu.cn/showproblem.php?pid=1429 终于开始能够做状态压缩的题了,虽然这只是状态压缩里面一道很简单的题. 状态压缩就是用二进制的思想来表示状态. 总共有10种钥匙,那么开一个(1<<10 的数组) 那么每次遇到一把钥匙我就用当前状态 |  钥匙转化为2进制的数值,然后遇到门的时候判断是否有对应的钥匙,只要用当前状态 & 门转化为2进制的值就可以.初始为0时,state=0,表示10个状态位都是0.那么每次遇到钥匙就改变相应的状态

hdu 1429 胜利大逃亡(续)(BFS+位压缩)

#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <set> #include <map> #include <string> #include <ma

HDU 3247 Resource Archiver AC自动机 + bfs + 状态压缩dp

题意:给定你n个文本串 ,m个模式串,怎么构造最短的新的文本串使得这个新的文本串包含n个文本串的所有信息且文本串的长度最短且不包含模式串. 解题思路:这里看题解撸的,首先我们算出两两文本串的距离(end数组标记文本和模式串的值不同,利用这个进行bfs算出两两之间的最短距离,注意到这里模式串的end是不能走到的.这里也不需要松弛操作),然后因为n只有10这么大,所以我们可以状态压缩  ,dp[i][j] 表示 压缩后状态为 i(二进制压缩,每i位表示第i个是否在)且 以j结尾的文本串的最小花费.这

poj1753 Flip Game(BFS+位压缩)

题目链接 http://poj.org/problem?id=1753 题意 一个棋盘上有16个格子,按4×4排列,每个格子有两面,两面的颜色分别为黑色和白色,游戏的每一轮选择一个格子翻动,翻动该格子意味着将该格子及其上下左右格子(如果存在的话)的黑面朝上变成白面朝上,反之亦然,游戏的目标是格子全部黑面朝上或者全部白面朝上.输入棋盘的初始状态,求最少经过多少轮可以达到游戏的目标. 思路 求最少轮数,我会想到使用bfs来解决(dfs也可以解决),但使用bfs求解,如果每个状态都直接存储下当前棋盘的

UVA-1533 Moving Pegs (BFS+位压缩)

Description Venture MFG Company, Inc. has made a game board. This game board has 15 holes and these holes are filled with pegs except one hole. A peg can jump over one or more consecutive peg s to the nearest empty hole along the straight line. As a

hdu 5025 Saving Tang Monk(bfs+状态压缩)

Problem Description <Journey to the West>(also <Monkey>) is one of the Four Great Classical Novels of Chinese literature. It was written by Wu Cheng'en during the Ming Dynasty. In this novel, Monkey King Sun Wukong, pig Zhu Bajie and Sha Wujin