【题解】 P1283 平板涂色

~先看题目内容:
1. 给出了N的范围 N **< 16** and 0 < x,y < 100
2. 颜色号为**不小于20的整数**

前者明示了我们这题可使用搜索做法

而非常有意思的是题目中并没有给出颜色号的具体数目

同时也说明了**存在存在颜色号1 与 3 却并不存在2的情况**

应该在代码中注意写法_(:зゝ∠)_

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

不难构建出一个代码结构 用结构体存储各个矩形数据
```cpp
struct node{
int lx, ly, rx, ry, color;
} f[20];
```
下面就要注意一些光看题目想不到的点了

先从样例走起 : Red → Blue → Red

不难发现很多矩形是在拿起刷子进行了标记以后才符合条件  所以在实现代码的过程中应注意循环遍历矩形时一定要**保证无符合条件矩形**时才能退出

剪枝问题:
- 目前次数超过已确定最小次数则退出
- 同一层某一矩形颜色如果曾被使用无必要重复计算

可行性问题:
- 当矩形位于顶端时可进行填涂
- 当矩形上端**全部**填涂完毕可进行填涂

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

然后便是一些我个人在做题的一些思路,仅供参考:
1. 为了避免dfs函数过于繁杂  将判断内容写到另一个函数中助于理清思路。
2. 判断是否填涂该矩形是否合法内容必须严谨。
3. 建立布尔型二维矩阵用于判断矩形合法性。
4. 在每一层dfs函数中建立布尔型数组判断改颜色是否被使用过。
5. 注意拿起了刷子是否合法 如果拿起刷子而未填涂则为不合法的。
6. ~~将题目中的x和y轴调换位置~~(个人习惯)

大致的建立一个模型并不难 主要考验一个调试能力

如果读者没有这种能力建议打开输出语句进行观察

本人AC代码:
~~22ms(勉勉强强)~~

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

```cpp
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{int lx, ly, rx, ry, color;} f[20];
int n, minn = 99999, nofc[20], tot; //别忘了给minn赋初值 tot存储已经填涂矩形数量
bool bol[20], bolmap[20][20];  //前者存储矩形使用情况 后者存储二维矩阵
bool cmp(node a, node b)
{return a.lx < b.lx;}
void dfs(int);
void paint(int color, int num)
{
    //printf("NOW IS %d %d\n", color, num);
    int l = 0, ind[20];  //ind数组存储符合条件矩形的下标 方便进行回溯
    bool flag = true, pp, flag2 = false; //flag用于判断是否还不存有符合填涂条件的矩形
    //pp 用于判断该矩形是否合法 flag2用于判断是否填涂了矩形 若为真进行下一层dfs
    while (flag){
        flag = false;
        for (int i = 0; i < n; ++i){
          if (!bol[i] and f[i].color == color){
              //printf("%d %d %d %d\n", tot, f[i].color, f[i].lx, f[i].ly);  //调试观察
            if (f[i].lx == 0){
              pp = true;}
              else {pp = false;}
              if (!pp) {pp = true;
              for (int j = f[i].ly; j <= f[i].ry; ++j)
                if (!bolmap[f[i].lx][j]) pp = false;}  //对矩形是否合法进行判断
              if (pp){
                  flag = flag2 = true;
                  tot++;
                  bol[i] = true;
                  ind[l++] = i;
                  //printf("paint : tot:%d color:%d lx:%d ly:%d i:%d\n", tot, f[i].color, f[i].lx, f[i].ly, i);
                  //输出合法矩形的各方面信息方便进行检查
                  for (int j = f[i].ly; j <= f[i].ry; ++j)
                    bolmap[f[i].rx][j] = true;
              }
          }
        }
    }
    /*for (int i = 0; i < l; ++i)
        printf("%d ", ind[i]);
    cout << endl;*/ //对ind数组的检查
    if (flag2) dfs(num); // 如果进行了填涂则这次拿起刷子是合法的进行dfs
    //getchar();getchar();
    for (int i = 0; i < l; ++i){
        tot--;
        bol[ind[i]] = false;
        //printf("clean : tot:%d color:%d lx:%d ly:%d i:%d\n", tot, f[ind[i]].color, f[ind[i]].lx, f[ind[i]].ly, ind[i]);
        for (int j = f[ind[i]].ly; j <= f[ind[i]].ry; ++j){
            bolmap[f[ind[i]].rx][j] = false;
        }
    } //利用之前所存的ind数组进行回溯
}
void dfs(int num)
{
    if (num > minn) return;  //最优性剪枝
    if (tot == n){
        minn = min(minn, num);
        return;
    }
    bool bolcolor[20];
    memset(bolcolor, 0, sizeof(bolcolor)); //意义不明
    for (int i = 0; i < n; ++i){
        if (!bol[i] and !bolcolor[f[i].color]){ //保证该矩形与该颜色都没被用过
            paint(f[i].color, num+1);
            bolcolor[f[i].color] = true;
        }
    }
}
int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n; ++i)
        scanf("%d %d %d %d %d", &f[i].lx, &f[i].ly, &f[i].rx, &f[i].ry, &f[i].color);
    sort(f, f+n, cmp);
    /*for (int i = 0; i < n; ++i){
        printf("\n%d %d %d %d %d\n", f[i].lx, f[i].ly, f[i].rx, f[i].ry, f[i].color);
    }*/
    //getchar();getchar(); //检查
    dfs(0);
    printf("%d", minn);
}
```

谢谢阅读

原文地址:https://www.cnblogs.com/NHDR233/p/11246722.html

时间: 2024-08-30 13:11:13

【题解】 P1283 平板涂色的相关文章

P1283 平板涂色

P1283 平板涂色 题目描述 CE数码公司开发了一种名为自动涂色机(APM)的产品.它能用预定的颜色给一块由不同尺寸且互不覆盖的矩形构成的平板涂色. 为了涂色,APM需要使用一组刷子.每个刷子涂一种不同的颜色C.APM拿起一把有颜色C的刷子,并给所有颜色为C且符合下面限制的矩形涂色: 为了避免颜料渗漏使颜色混合,一个矩形只能在所有紧靠它上方的矩形涂色后,才能涂色.例如图中矩形F必须在C和D涂色后才能涂色.注意,每一个矩形必须立刻涂满,不能只涂一部分. 写一个程序求一个使APM拿起刷子次数最少的

平板涂色

CE数码公司开发了一种名为自动涂色机(APM)的产品.它能用预定的颜色给一块由不同尺寸且互不覆盖的矩形构成的平板涂色. 为了涂色,APM需要使用一组刷子.每个刷子涂一种不同的颜色C.APM拿起一把有颜色C的刷子,并给所有颜色为C且符合下面限制的矩形涂色: 为了避免颜料渗漏使颜色混合,一个矩形只能在所有紧靠它上方的矩形涂色后,才能涂色.例如图中矩形F必须在C和D涂色后才能涂色.注意,每一个矩形必须立刻涂满,不能只涂一部分. 写一个 1 #include<iostream> 2 #include&

POJ1691平板涂色

题目描述 原题来自:POJ 1691 CE 数码公司开发了一种名为自动涂色机(APM)的产品.它能用预定的颜色给一块由不同尺寸且互不覆盖的矩形构成的平板涂色. 为了涂色,APM 需要使用一组刷子.每个刷子蘸了颜色 C .APM 拿起一把蘸有颜色 C 的刷子,并给所有颜色为 C 的矩形涂色.请注意,涂色有顺序要求:为了避免颜料渗漏使颜色混合,一个矩形只能在所有紧靠它上方的矩形涂色后,才能涂色.例如图中矩形 F 必须在 C 和 DDD 涂色后才能涂色.注意,每一个矩形必须立刻涂满,不能只涂一部分.

[算法小练][图][拓扑排序+深度优先搜索] 平板涂色问题

说在前面 本题是一道经典题目,多做经典题目可以节省很多学习时间,比如本题就包含了许多知识:回溯+剪枝+拓扑排序+深度优先搜索.[动态规划方法另作讨论] 关键代码 题: CE数码公司开发了一种名为自动涂色机(APM)的产品.它能用预定的颜色给一块由不同尺寸且互不覆盖的矩形构成的平板涂色. 为了涂色,APM需要使用一组刷子.每个刷子涂一种不同的颜色C.APM拿起一把有颜色C的刷子,并给所有颜色为C且符合下面限制的矩形涂色: 为了避免颜料渗漏使颜色混合,一个矩形只能在所有紧靠它上方的矩形涂色后,才能涂

#10023. 「一本通 1.3 练习 2」平板涂色

#include<bits/stdc++.h> #define lop(x,m,n) for(int x=m;x<=n;x++) using namespace std; int n; struct node{ int x1,y1,x2,y2,se; }sq[20]; int used[20]={0}; int maxx,maxy; bool b[40][40]={0}; void init() { maxx=-1,maxy=-1; scanf("%d",&n

[BZOJ 1260][CQOI2007]涂色paint 题解(区间DP)

[BZOJ 1260][CQOI2007]涂色paint Description 假设你有一条长度为5的木版,初始时没有涂过任何颜色.你希望把它的5个单位长度分别涂上红.绿.蓝.绿.红色,用一个长度为5的字符串表示这个目标:RGBGR. 每次你可以把一段连续的木版涂成一个给定的颜色,后涂的颜色覆盖先涂的颜色.例如第一次把木版涂成RRRRR,第二次涂成RGGGR,第三次涂成RGBGR,达到目标. 用尽量少的涂色次数达到目标. Input 输入仅一行,包含一个长度为n的字符串,即涂色目标.字符串中的

BZOJ 1260 [CQOI2007]涂色paint(区间DP)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1260 [题目大意] 假设你有一条长度为n的木版,初始时没有涂过任何颜色 每次你可以把一段连续的木版涂成一个给定的颜色,后涂的颜色覆盖先涂的颜色 求最少的涂色次数达到目标状态 [题解] dp[i][j]表示涂抹i到j的最优答案, 显然当i和j相同时,可以从i+1……j,i……j-1,i+1……j-1转移过来, 同时也可以从两个区间组合得到. [代码] #include <cstdio>

【DP】BZOJ 1260: [CQOI2007]涂色paint

1260: [CQOI2007]涂色paint Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 893  Solved: 540[Submit][Status][Discuss] Description 假设你有一条长度为5的木版,初始时没有涂过任何颜色.你希望把它的5个单位长度分别涂上红.绿.蓝.绿.红色,用一个长度为5的字符串表示这个目标:RGBGR. 每次你可以把一段连续的木版涂成一个给定的颜色,后涂的颜色覆盖先涂的颜色.例如第一次把木版涂成R

1260: [CQOI2007]涂色paint

Description 假设你有一条长度为5的木版,初始时没有涂过任何颜色.你希望把它的5个单位长度分别涂上红.绿.蓝.绿.红色,用一个长度为5的字符串表示这个目标:RGBGR. 每次你可以把一段连续的木版涂成一个给定的颜色,后涂的颜色覆盖先涂的颜色.例如第一次把木版涂成RRRRR,第二次涂成RGGGR,第三次涂成RGBGR,达到目标. 用尽量少的涂色次数达到目标. Input 输入仅一行,包含一个长度为n的字符串,即涂色目标.字符串中的每个字符都是一个大写字母,不同的字母代表不同颜色,相同的字