zoukankan      html  css  js  c++  java
  • 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;
    }
    -------------------------------------------------------

    kedebug

    Department of Computer Science and Engineering,

    Shanghai Jiao Tong University

    E-mail: kedebug0@gmail.com

    GitHub: http://github.com/kedebug

    -------------------------------------------------------

  • 相关阅读:
    vue 中的单元测试
    redux-学习总结
    React-学习总结
    vuecli 中 chainWebpack 的常用操作
    常用 vue-config.js 配置
    JavaScript 中的 MVC、MVP、MVVM
    日常工作中 @vue/cli 需要关注的一些配置
    Electron 构建超时问题
    JSBridge 原理与封装
    Three.js 之相机
  • 原文地址:https://www.cnblogs.com/kedebug/p/3003103.html
Copyright © 2011-2022 走看看