码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-02-10 15:30:31      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:图论   hdu   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 represented as a 2*n grid and each grid will be painted only one color. Annie has a brush which could paint a rectangular area of the wall at a single step. The paint could be overlap and the newly painted color will replace the older one.
  For a given pattern of the wall, your task is to help Annie find out the minimum possible number of painting steps. You can assume that the wall remains unpainted until Annie paint some colors on it.
 

Input
There are multiple test cases in the input. The first line contains the number of test cases.
  For each test case, the first line contains the only integer n indicating the length of the wall. (1 <= n <= 8)
  Two lines follow, denoting the expected pattern of the wall. The color is represented by a single capital letter.
  See the sample input for further details.
 

Output
For each test case, output only one integer denoting the minimum number of steps.
 

Sample Input
3 3 ABA CBC 3 BAA CCB 3 BBB BAB
 

Sample Output
Case #1: 3 Case #2: 3 Case #3: 2
 

Source
The 36th ACM/ICPC Asia Regional Shanghai Site —— Warmup

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

题目大意:给你一个2 * n的矩阵,给里面的子矩阵涂色,每次涂一种颜色,同一个区域被涂两次则第一次涂的会被第二次覆盖,求最少要涂几次能达到目标状态

题目分析:因为其中状态很多而n又不大,考虑采用状压搜索,把每种状态都加入队列,一个vis[1 << 16]数组标记每一位的状态,如果是1表示该位置已经是目标色,0则表示还未涂色,状态有很多种,一共分成6类,第一行左右扩展,第二行左右扩展,第一行第二行共同左右扩展,注意一些剪枝,详细见程序注释



#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

struct NODE
{
    int val;
    int step;
};

bool vis[1 << 16];  //标记各位置是否达到目标色
char s[20];
int n;

int BFS()
{
    queue<NODE> q;
    NODE st, cur, next;
    memset(vis, false, sizeof(vis));
    vis[0] = true;
    st.val = 0;
    st.step = 0;
    q.push(st);
    while(!q.empty())
    {
        cur = q.front();
        q.pop();
        //各位都为1则涂色完成
        if(cur.val == (1 << 2 * n) - 1) 
            return cur.step;
        for(int i = 0; i < 2 * n; i++)
        {
            //如果当前位置已经涂色,则不作为拓展原点
            if((1 << i) & cur.val)
                continue;
            next = cur;
            next.step ++;
            int tmp = 0;
            //单行向右扩展
            int nn = i < n ? n : 2 * n;
            for(int j = i; j < nn; j++)
            {
                //若该点已经涂色则退出循环
                if((1 << j) & cur.val)
                    break;
                //若该点未涂色且颜色和目标色相同则上色
                if(s[j] == s[i])
                    tmp = tmp | (1 << j);
            }
            //单行向左扩展
            nn = i < n ? 0 : n;
            for(int j = i - 1; j >= nn; j--)
            {
                if((1 << j) & cur.val)
                    break;
                if(s[j] == s[i])
                    tmp = tmp | (1 << j);
            }
            //将所有状态分离,若出现新的状态则加入队列
            for(int j = tmp; j; j = tmp & (j - 1))
            {
                int val = cur.val | j;
                if(!vis[val])
                {
                    vis[val] = true;
                    next.val = val;
                    q.push(next);
                }
            }
            //双行扩展通过第一行来得到第二行,若当前对应
            //的第二行的位置已经涂色,则该列不作为拓展原点
            if(i >= n || (cur.val & (1 << i + n)))
                continue;
            tmp = 0;
            for(int j = i; j < n; j++)
            {
                if(((1 << j) & cur.val) || ((1 << (j + n)) & cur.val))
                    break;
                if(s[j] == s[i])
                    tmp |= (1 << j);
                if(s[j + n] == s[i])
                    tmp |= (1 << (j + n));
            }
            for(int j = i - 1; j >= 0; j--)
            {
                if(((1 << j) & cur.val) || ((1 << (j + n)) & cur.val))
                    break;
                if(s[j] == s[i])
                    tmp |= (1 << j);
                if(s[j + n] == s[i])
                    tmp |= (1 << (j + n));
            }
            for(int j = tmp; j; j = tmp & (j - 1))
            {
                int val = cur.val | j;
                if(!vis[val])
                {   
                    vis[val] = true;
                    next.val = val;
                    q.push(next);
                }
            }
        }
    }
    return 0;
}

int main()
{
    int T;
    scanf("%d", &T);
    for(int ca = 1; ca <= T; ca++)
    {
        scanf("%d", &n);
        scanf("%s %s", s, s + n); //将两行读做一行
        printf("Case #%d: %d\n", ca, BFS());
    }
}


 

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

标签:图论   hdu   bfs   状态压缩   

原文地址:http://blog.csdn.net/tc_to_top/article/details/43701909

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!