洛谷P1283 平板涂色 &&一本通1445:平板涂色
题目描述
CE数码公司开发了一种名为自动涂色机(APM)的产品。它能用预定的颜色给一块由不同尺寸且互不覆盖的矩形构成的平板涂色。
为了涂色,APM需要使用一组刷子。每个刷子涂一种不同的颜色C。APM拿起一把有颜色C的刷子,并给所有颜色为C且符合下面限制的矩形涂色:
为了避免颜料渗漏使颜色混合,一个矩形只能在所有紧靠它上方的矩形涂色后,才能涂色。例如图中矩形F必须在C和D涂色后才能涂色。注意,每一个矩形必须立刻涂满,不能只涂一部分。
写一个程序求一个使APM拿起刷子次数最少的涂色方案。注意,如果一把刷子被拿起超过一次,则每一次都必须记入总数中。
【输入】
第一行为矩形的个数N。下面有N行描述了N个矩形。每个矩形有5个整数描述,左上角的y坐标和x坐标,右下角的y坐标和x坐标,以及预定颜色。
颜色号为1到20的整数。
平板的左上角坐标总是(0, 0)。
坐标的范围是0..99。N小于16。
【输出】
拿起刷子的最少次数。
【输入样例】
7
0 0 2 2 1
0 2 1 6 2
2 0 4 2 1
1 2 4 4 2
1 4 3 6 1
4 0 6 4 1
3 4 6 6 2
【输出样例】
3
蒟蒻看到这题,先是mengbi,表示不会DP,只能搜索(+剪枝)
这数据竟然过了(n<16)
搜索思路
读入数据,统计颜色,然后每个颜色都试一遍,即把该颜色的且能涂的砖涂上。
下一次涂色不能涂上次涂过的色。涂完了记录结果
这不会超时吗老铁
为了不超时,加了两个剪枝
最优化剪枝:当前涂色次数大于等于当前答案,直接退出(这个好理解吧)
可行性剪枝:如果当前一个砖都没有涂到,直接退出(如果接着搜,会多一个次数,可能还会死循环,,,)
至于判断该砖是否能涂,先预处理,把紧邻该砖上方的砖用数组记录下来,再判断那些砖是否被涂
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<vector>
#define ll long long
using namespace std;
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
while(isdigit(ch)) s=s*10+ch-'0',ch=getchar();
return s*w;
}
struct lbq //结构体 a1b1 该砖左上角坐标 a2b2 右下角坐标 x 颜色
{
int a1,b1,a2,b2,x;
}a[20];
int ccmp(lbq a,lbq b)
{
if(a.a1!=b.a1) return a.a1<b.a1;
return a.b1<b.b1;
}
bool d=false;
int de[20];//de数组表示是否有该颜色
int n,m,ans=999,b[20],fk[20][20]; //b数组代表该砖是否被涂
bool OK(int o)
{
for(int i=1;i<=n;i++)
if(fk[o][i]&&!b[i]) return false; //如果i砖下面紧邻o,但i没涂过,返回false
return true;
}
void dfs(int o,int pq,int xx)//o 涂色次数 pq 涂过颜色的砖 xx 上次涂的颜色
{
if(o>=ans) return;//当前涂色次数大于等于当前答案,直接退出
if(pq==n)//涂完了,记录答案
{
ans=o;
return;
}
for(int i=1;i<=m;i++)//枚举颜色
{
int oj=0;//代表现在用这个颜色涂的砖数
if(i!=xx&&de[i])//如果有这个颜色,并且这种颜色上次没用过
{
for(int j=1;j<=n;j++) //涂色
if(!b[j]&&a[j].x==i&&OK(j))
//如果没涂过该砖,并且能涂
b[j]=1,oj++;
else
if(b[j]&&a[j].x==i)
b[j]++;
if(oj>0)
dfs(o+1,pq+oj,i);//如果涂了砖,进行下一步
for(int j=n;j>=1;j--)//回溯一步
if(b[j]==1&&a[j].x==i&&OK(j))
b[j]=0,oj--;
else
if(b[j]>1&&a[j].x==i)
b[j]--;
}
}
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
a[i].a1=read(),a[i].b1=read(),a[i].a2=read(),a[i].b2=read(),a[i].x=read(),
a[i].a1++,a[i].b1++,de[a[i].x]++;//记录颜色
for(int i=1;i<=20;i++)
if(de[i])
m=i; //求最大颜色编号
sort(a+1,a+n+1,ccmp);//按左上角坐标大小从小到大排序(先考虑纵,再考虑横)
for(int i=2;i<=n;i++)
for(int j=i-1;j>=1;j--)//fk[i][j]表示第i个砖是否紧邻上方第j个砖
if(a[i].a1==a[j].a2+1&&((a[i].b1>=a[j].b1&&a[i].b1<=a[j].b2)||(a[i].b2>=a[j].b1&&a[i].b2<=a[j].b2)))
fk[i][j]=1;//如果i砖的最上面紧邻j砖最下面,且两砖横坐标有重叠,即j砖为i砖紧邻上面的砖
dfs(0,0,0);
printf("%d",ans);//结果
return 0;
}
洛谷P1283 平板涂色 &&一本通1445:平板涂色的更多相关文章
- 【题解】洛谷P1283 平板涂色(搜索+暴力)
思路 看到n<16 整个坐标<100 肯定想到暴力啊 蒟蒻来一发最简单易懂的题解(因为不会DP哈 首先我们用map数组来存坐标图 注意前面的坐标需要加1 因为输入的是坐标 而我们需要的是格 ...
- 洛谷P3703 [SDOI2017]树点涂色(LCT,dfn序,线段树,倍增LCA)
洛谷题目传送门 闲话 这是所有LCT题目中的一个异类. 之所以认为是LCT题目,是因为本题思路的瓶颈就在于如何去维护同颜色的点的集合. 只不过做着做着,感觉后来的思路(dfn序,线段树,LCA)似乎要 ...
- 洛谷 P4170 [CQOI2007]涂色
题目描述 假设你有一条长度为5的木版,初始时没有涂过任何颜色.你希望把它的5个单位长度分别涂上红.绿.蓝.绿.红色,用一个长度为5的字符串表示这个目标:RGBGR. 每次你可以把一段连续的木版涂成一个 ...
- 【算法•日更•第三十期】区间动态规划:洛谷P4170 [CQOI2007]涂色题解
废话不多说,直接上题: P4170 [CQOI2007]涂色 题目描述 假设你有一条长度为5的木版,初始时没有涂过任何颜色.你希望把它的5个单位长度分别涂上红.绿.蓝.绿.红色,用一个长度为5的字符 ...
- 洛谷P1162—填涂颜色
这应该是是第一次记录洛谷题库里的题目吧: 题目描述 由数字00组成的方阵中,有一任意形状闭合圈,闭合圈由数字11构成,围圈时只走上下左右44个方向.现要求把闭合圈内的所有空间都填写成22.例如:6 \ ...
- 【洛谷p2669】【一本通p1100】金币
(今天高产) 金币[传送门] 洛谷上的算法标签 自我感觉主要靠循环 这道题是2015年NOIp普及组的题,其实还是很简单的.但为什么写这道题呢? 这道题第一次接触是在一本通刷题的时候,当时学循环结构, ...
- 【洛谷p1015】【一本通p1309】回文数(noip1999)
(过了这个题灰常灰常开心) 好像前两道忘记了传送门: 回文数[传送门] 洛谷算法标签: 其实还有高精度 这个题困死在了十六进制,后来想了想,我们在c[i]中存入一个大于十的数之前的程序也可以实现回文( ...
- BZOJ2721或洛谷1445 [Violet]樱花
BZOJ原题链接 洛谷原题链接 其实推导很简单,只不过我太菜了想不到...又双叒叕去看题解 简单写下推导过程. 原方程:\[\dfrac{1}{x} + \dfrac{1}{y} = \dfrac{1 ...
- 「SDOI2014」旅行(信息学奥赛一本通 1564)(洛谷 3313)
题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我 ...
随机推荐
- [LeetCode] 42. Trapping Rain Water 收集雨水
Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...
- Python程序中的线程操作-创建多线程
目录 一.python线程模块的选择 二.threading模块 三.通过threading.Thread类创建线程 3.1 创建线程的方式一 3.2 创建线程的方式二 四.多线程与多进程 4.1 p ...
- 转载-ThreadPoolExecutor里面4种拒绝策略(详细)
原文链接:https://blog.csdn.net/wjs19930820/article/details/79849050 1 /** * 定义异步任务执行线程池 */ @Configuratio ...
- MySQL属性SQL_MODE学习笔记
最近在学习<MySQL技术内幕:SQL编程>并做了笔记,本博客是一篇笔记类型博客,分享出来,方便自己以后复习,也可以帮助其他人 SQL_MODE:MySQL特有的一个属性,用途很广,可以通 ...
- pytest框架之allure报告生成
一.关于安装 allure是跟pytest一起集成使用的,所以需要同时安装pytest以及allure-pytest插件: pip install pytest pip install allure- ...
- redis设置、查看和校验密码
Redis没有实现访问控制这个功能,但是它提供了一个轻量级的认证方式(密码),可以通过编辑[redis.conf]配置文件来启用认证,这里简单介绍一下Redis中如何设置.查看和校验密码(登录验证和操 ...
- jsp页面科学计数法显示问题的解决办法
在JSP页面中返回的double类型的数值,如果数值过大,就会被显示成科学计数法. 这个问题通常出现在表单填写的input中,因此是必须要解决的问题. JSTL提供了标准的数值格式化标签,使用上非常简 ...
- PHP echo一个对象报语法错误,为什么?
为什么直接echo一个对象就会报语法错误,而如果这个对象实现了__toString方法后就可以直接输出呢? 原因是echo本来可以打印一个对象,而且也实现了这个接口,但是PHP对其做了个限制,只有实现 ...
- Django多进程滚动日志的问题
使用RotatingFileHandler控制日志文件的大小 # settings.py LOGGING = { ... 'handlers': { ... 'file': { 'level': 'I ...
- win7系统下安装Ubuntu18.04组成双系统
最近在闲鱼上花了350大洋淘到了一台tinkpad sl510,这大概是一台发布于2009年的一台电脑了吧,处理器是酷睿二t440,2Gddr3的显卡,让我有点意外的是这台电脑的硬盘是7200转的32 ...