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

每日一宏

#define 大法师 dfs

大法师万岁

题目

题目描述

CE 数码公司开发了一种名为自动涂色机(APM)的产品。它能用预定的颜色给一块由不同尺寸且互不覆盖的矩形构成的平板涂色。

在这里插入图片描述

为了涂色,APM 需要使用一组刷子。每个刷子蘸了颜色 C 。APM 拿起一把蘸有颜色 C 的刷子,并给所有颜色为 C 的矩形涂色。请注意,涂色有顺序要求:为了避免颜料渗漏使颜色混合,一个矩形只能在所有紧靠它上方的矩形涂色后,才能涂色。例如图中矩形 F 必须在 C 和 D 涂色后才能涂色。注意,每一个矩形必须立刻涂满,不能只涂一部分。

写一个程序求一个使 APM 拿起刷子次数最少的涂色方案。注意,如果一把刷子被拿起超过一次,则每一次都必须记入总数中。

输入格式

第一行为矩形的个数 N 。
下面有 N 行描述了 N 个矩形。每个矩形有 5 个整数描述,左上角的 y 坐标和 x 坐标,右下角的 y 坐标和 x 坐标,以及预定颜色。

输出格式

一行一个整数,表示拿起刷子的最少次数。

样例

输入
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

思路

一眼大法师
因为样例太水所以暴力过了
只需要用深搜遍历每条路
若是到了第n次,就更新答案返回
春春的暴力题

代码

#include<bits/stdc++.h>
using namespace std;
int n;
int mins=0x3f3f3f3f;
bool aa[105][105],vis[25];
struct pb{
	int zx,zy;
	int yx,yy;
	int col;
}a[25];
bool sao(int,int,int);
void tu(int);
void mo(int);
void dfs(int,int,int); 
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].zx>>a[i].zy>>a[i].yx>>a[i].yy>>a[i].col;
		a[i].zx++;
		a[i].zy++;
		a[i].yx++;
		a[i].yy++;
		for(int j=a[i].zx+1;j<=a[i].yx;j++){//每一个点初始化为1,与0区别开
			for(int k=a[i].zy+1;k<=a[i].yy;k++){//左端点一定要加一因为点可能会重复赋值
				aa[k][j]=1;
			}
		}
	}
	for(int i=1;i<=n;i++){
		if(a[i].zx==1&&!vis[i]){//从第一层开始搜
			vis[i]=1;
			tu(i);
			dfs(i,1,1);
			mo(i);
			vis[i]=0;//回溯
		}
	}
	cout<<mins;
	return 0;
}
bool sao(int y,int b,int e){//扫一遍当前矩形上面一行
	for(int i=b+1;i<=e;i++){
		if(aa[y][i]){//如果有没涂的就false掉(1代表没涂)
			return false;
		}
	}
	return true;
}
void tu(int i){//把这个矩形涂上
	for(int k=a[i].zx+1;k<=a[i].yx;k++){
		for(int j=a[i].zy+1;j<=a[i].yy;j++){
			aa[k][j]=0;
		}
	}
}
void mo(int i){//抹去颜色
	for(int k=a[i].zx+1;k<=a[i].yx;k++){
		for(int j=a[i].zy+1;j<=a[i].yy;j++){
			aa[k][j]=1;
		}
	}
}
void dfs(int ago,int k,int s){
	if(s>mins){//小小小剪枝,如果当前s比当前找到的最优解还大,直接return
		return;
	}
	if(k==n){
		mins=min(mins,s);
		return;
	}
	for(int i=1;i<=n;i++){
		if(!vis[i]){
			if(sao(a[i].zx,a[i].zy,a[i].yy)){
				vis[i]=1;
				tu(i);	
				if(a[i].col!=a[ago].col){//去下一个矩形的时候判断颜色
					dfs(i,k+1,s+1);//若更换颜色,s++
				}
				else{
					dfs(i,k+1,s);
				}
				vis[i]=0;
				mo(i);
			}
		}
	}
}

看完后是不是很吃惊,
这么暴力都过了
俺也一样

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值