题解 P1283 平板涂色
Posted nhdr233
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解 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 nodeint 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);
```
谢谢阅读
以上是关于题解 P1283 平板涂色的主要内容,如果未能解决你的问题,请参考以下文章