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;

}

你可能感兴趣的:(paint)