POJ - 1691 Painting A Board (状态压缩 + 暴力)

题目大意:要将一个大矩形內的所有小矩形涂色,涂色要求,只有该矩形上面的所有矩形都涂色了才可以涂该颜色,换一种填涂的颜色就要花费一点体力值,问填涂完需要花费的最小体力值

解题思路:先处理一下填涂该矩形的前提条件,我用了一个can数组表示填涂该矩形时要满足的状态量

用dp[color][state]表示当前用的颜色是color,填涂的状态为state时所用的最少体力值

然后暴力得出转换和结果

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define maxn 15
#define maxc 22
#define maxs (1 << 15)
#define INF 0x3f3f3f3f

struct Rectangles{
    int x1, x2, y1, y2, color;
}Rec[maxn];

struct paiting{
    int s, color;
}start;

int n;
int can[maxn];
int dp[maxc][maxs];

bool judge(int i, int j) {
    if (Rec[j].y2 <= Rec[i].y1)
        if (((Rec[j].x1 <= Rec[i].x1 && Rec[j].x2 > Rec[i].x1 && Rec[j].x2 <= Rec[i].x2) || (Rec[j].x2 >= Rec[i].x2 && Rec[j].x1 >= Rec[i].x1 && Rec[j].x1 < Rec[i].x2)))
            return true;
    return false;
}

void init() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%d%d%d%d%d", &Rec[i].y1, &Rec[i].x1, &Rec[i].y2, &Rec[i].x2, &Rec[i].color);
    memset(can, 0, sizeof(can));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (i == j)
                continue;
            if (judge(i, j))
                can[i] |= (1 << j);
        }
    }
    memset(dp, 0x3f, sizeof(dp));
    dp[0][0] = 0;
}

void solve() {
    queue<paiting> q;
    start.s = 0;
    start.color = 0;
    q.push(start);
    while (!q.empty()) {
        paiting t = q.front();
        q.pop();
        int state = t.s;
        int color = t.color;
        for (int i = 0; i < n; i++)
            if ((state & (1 << i)) == 0 && (state & can[i]) == can[i]) {
                if (Rec[i].color == color) {
                    dp[color][state | (1 << i)] = min(dp[color][state | (1 << i)], dp[color][state]);
                }
                else {
                    dp[Rec[i].color][state | (1 << i)] = min(dp[Rec[i].color][state | (1 << i)], dp[color][state] + 1);
                }
                paiting tt;
                tt.s = state | (1 << i);
                tt.color = Rec[i].color;
                q.push(tt);
            }
    }

    int ans = INF;
    for (int i = 0; i < maxc; i++)
        ans = min(ans, dp[i][(1 << n) - 1]);
    printf("%d\n", ans);
}

int main() {
    int test;
    scanf("%d", &test);
    while (test--) {
        init();
        solve();

    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-13 08:05:25

POJ - 1691 Painting A Board (状态压缩 + 暴力)的相关文章

POJ 1691 Painting A Board(DFS)

链接 题意 : 看了好长时间终于看懂题目了,将一个大矩形划分成若干小矩形,告诉你每个小矩形的左上角那个点和右下角那个点的坐标,告诉你这个小矩形要涂的颜色,每个颜色对应一个刷子,问你最少要使用几次刷子.因为你要刷一个矩形之前,必须把这个矩形上方与之直接相邻的所有矩形先刷掉才能刷这个,如果你先用了红色的刷子,然后又用了蓝色的刷子,最后又用了红色的刷子,这算是3次使用而不是两次,样例中,用红色刷B所以D也可以刷了,用蓝色先刷A,然后可以刷C,因为B刷了所以E也可以刷了,最后换刷子把剩下的刷掉,总共三次

POJ 1691 Painting A Board

题目大意: 墙上有一块区域被分成了n个矩形,每个矩形要涂上各自的颜色.为了保证完美要求这一块区域可以进行涂色的条件是它上方的所有区域都已经涂好颜色,这样就不会有后续的操作影响这块区域的颜色.但是如果两块区域颜色不同就要换涂颜色用的刷子.问最少需要换几次. 解题思路: 区域涂色的大体次序是由拓扑排序决定的,当有多个区域在同一层次时需要枚举这些区域来保证换刷子的次数最小. 下面是代码: #include <stdio.h> #include <stdlib.h> struct node

[poj 1691] Painting A Board dfs+拓扑排序

Painting A Board Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 3611 Accepted: 1795 Description The CE digital company has built an Automatic Painting Machine (APM) to paint a flat board fully covered by adjacent non-overlapping rectangle

poj 1691 Painting A Board 拓扑序+dfs

题意: 一个木板上被分成了很多区域,每个区域要涂上一种特定的颜色,当涂一个区域的时候,它上方与它有重合部分的区域必须之前要涂好.求最少需要拿几次画笔(拿一次画笔可以涂颜色相同的多个区域). 分析: 上方与它有重合部分的区域必须之前要涂好这个限制可以用拓扑序来描述,每次涂有很多种可以涂的颜色,dfs就可以了.dfs的状态空间维数定为拿笔的次数,每次枚举可以涂的颜色.要注意的是dfs过程中要慎用全局变量..否则每个维度需枚举的东西被下一维改了就跪了... 代码: //poj 1691 //sep9

poj - 1691 - Painting A Board(状态压缩dp)

题意:N(1 <= N <= 15)个矩形,每个矩形要涂上指定的颜色C(1 <= C <= 20),如果给一个矩形涂色,那么与它相邻的上方矩形必须已经涂色,问最少要取几次画笔. 题目链接:http://poj.org/problem?id=1691 -->>状态:dp[S][color] 表示达到状态 S 且最后一次涂色为 color 时的最小取画笔数 状态转移方程:dp[S][color] = min(dp[S][color], dp[sub][i]); 或者 dp[

poj 3254 Corn Fields ,状态压缩DP

题目链接 题意: 一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求两个相邻的方格不能同时放牛,即牛与牛不能相邻.问有多少种放牛方案(一头牛都不放也是一种方案) state[i] 表示对于一行,保证不相邻的方案 状态:dp[i][ state[j] ]  在状态为state[j]时,到第i行符合条件的可以放牛的方案数 状态转移:dp[i][ state[j] ] =Sigma dp[i-1][state'] (state'为符合条

POJ 1038 Bugs Integrated, Inc. 状态压缩DP

题目来源:1038 Bugs Integrated, Inc. 题意:最多能放多少个2*3的矩形 思路:状态压缩DP啊 初学 看着大牛的代码搞下来的  总算搞懂了 接下来会更轻松吧 3进制代表前2行的状态(i行和i-1行)1代表i-1行占位 2代表i行占位 i-1不管有没有占位都不会影响的0代表i行和i-1行都空闲 然后枚举状态dfs更新状态 话说就不能没写深搜了 有点不会了 #include <cstdio> #include <cstring> #include <alg

[POJ 2411] Mondriaan&#39;s Dream 状态压缩DP

题意 给定一个 n * m 的矩形. 问有多少种多米诺骨牌覆盖. n, m <= 11 . 实现 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cctype> 5 #define F(i, a, b) for (register int i = (a); i <= (b); i++) 6 #define LL long long 7 inline

HDU 1557 权利指数 状态压缩 暴力

HDU 1557 权利指数 状态压缩 暴力 ACM 题目地址:HDU 1557 权利指数 题意: 中文题,不解释. 分析: 枚举所有集合,计算集合中的和,判断集合里面的团体是否为关键团队. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * File: 1557.cpp * Create Date: 2014-06-28 14:47:58 * Descripton: brute force/ set */ #include <cstdio&g