POJ 1691 Painting A Board(状态压缩DP + 记忆化搜索)

题意:

有一个矩形框由n个小的矩形组成,现在要把每个矩形涂上一种颜色c(可相同可不同,如下图)。为了保证涂的质量,涂每个小矩阵有一个条件,就是位于它上面,并且与它有连接的小矩形必须先涂好。当然满足条件的同一种颜色可以一起涂,问最少需要多少把刷子(每把刷子一种颜色)。

黑书 146 :平板涂色

思路:

1. 矩形的数量不超过 15,所以自然的联想到利用状态压缩去解决问题,并且为了解决无后效性,还必须增加一维,dp[i][s] 表示以 i 结尾的状态 s 的最小;

2. 首先预处理,矩形 i 上面的矩形编号,为下面的解题作个很好的铺垫;

3. 剩下的工作就是枚举:i 前一个所刷的矩形,思路很简单就不多述了。注意循环的时候 s 放在前面,这样才能保证求得的结果不相互影响;

 

#include <iostream>
#include <algorithm>
using namespace std;

const int INFS = 0x3FFFFFFF;

struct POINT {
    int x1, y1, x2, y2;
    int color;
} rect[20] ;

int up[20], dp[15][1<<15];

bool judge(int i, int j) {
    // whether j is upper to i
    if (rect[j].x2 != rect[i].x1) return false;
    if (rect[j].y2 <= rect[i].y1) return false;
    if (rect[j].y1 >= rect[i].y2) return false;
    return true;
}

int workout(int n) {
    for (int i = 0; i < n; i++) {
        up[i] = 0;
        for (int j = 0; j < n; j++)
            if (judge(i, j)) up[i] |= (1<<j);
    }

    int ENDS = (1<<n) - 1;

    for (int i = 0; i < n; i++)
        for (int s = 0; s <= ENDS; s++)
            dp[i][s] = INFS;
    for (int i = 0; i < n; i++)
        if (up[i] == 0) dp[i][1<<i] = 1;

    for (int s = 0; s <= ENDS; s++) {
        for (int i = 0; i < n; i++) {
            if (s & (1<<i)) continue;
            if ((s & up[i]) != up[i]) continue;
            for (int j = 0; j < n; j++) {
                if (!(s & (1<<j))) continue;
                int now = s | (1<<i);
                int value = dp[j][s];
                if (rect[i].color != rect[j].color) value += 1;
                dp[i][now] = min(dp[i][now], value);
            }
        }
    }
    int ans = INFS;
    for (int i = 0; i < n; i++)
        ans = min(ans, dp[i][ENDS]);
    return ans;
}

int main() {
    int cases;
    scanf("%d", &cases);
    while (cases--) {
        int n;
        scanf("%d", &n);
        for (int i = 0; i < n; i++)
            scanf("%d%d%d%d%d", &rect[i].x1, &rect[i].y1, &rect[i].x2, &rect[i].y2, &rect[i].color);
        printf("%d\n", workout(n));
    }
    return 0;
}
posted @ 2013-04-06 22:34  kedebug  阅读(430)  评论(0编辑  收藏  举报