平板涂色
题目描述
CE 数字公司已经建立了一个自动喷漆机 (APM), 以绘制一个平面板完全覆盖的相邻的不同大小的非重叠矩形每一个预定义的颜色。
为了给主板上色, APM 可以访问一组画笔。每个画笔都有一个不同的颜色 C。APM 使用颜色 c 选择一个画笔, 并绘制所有可能的具有预定义颜色 c 的矩形, 并
具有以下限制: 为了避免泄漏颜料和混合颜色, 只有在上面的所有矩形都有已经被粉刷过了。
具有以下限制: 为了避免泄漏颜料和混合颜色, 只有在上面的所有矩形都有已经被粉刷过了。
例如, 在图1中标记为 F 的矩形在绘制矩形 C 和 D 之后才被绘制。请注意, 必须同时绘制每个矩形, 即不允许对一个矩形进行部分绘制。
您要编写一个用于 APM 的程序来绘制给定的主板, 以使画笔拾取的数量最小。请注意, 如果一个画笔多次被拾取, 所有的拾取都将被计数。
您要编写一个用于 APM 的程序来绘制给定的主板, 以使画笔拾取的数量最小。请注意, 如果一个画笔多次被拾取, 所有的拾取都将被计数。
输入
输入文件的第一行包含整数 N, 矩形的数目, 后跟描述矩形的 n 行。每个矩形 R 在一行中指定为5个整数: r 左上角的 y 和 x 坐标, r 右下角的 y 和 x 坐标, 后跟 r 的颜色代码.
请注意:
- 颜色代码是一个整数, 范围为1。20。
- 板坐标的左上角总是 (00)。
- 坐标在范围 0..。99。
- N 的范围为 1.. 15。
输出
一行, 显示画笔拾取的最小数目
样例输入
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
说明/提示
1≤Ci≤20,0≤xi,yi≤99,1≤N≤16。
思路:
别人的思路:
- 先用结构体记录数据
- 然后循环记录(记录一个矩形的上面需要涂的矩形)
-
深搜并且回溯
我的思路:
-
具体看代码,代码里有注释
代码:
#include<bits/stdc++.h>
using namespace std;
struct candy{
int x1,y1,x2,y2,col;//结构体输入
}pd[51];
vector<int> dp[51];//可变数组
int n,ans=2147483647,vis[51];
inline int check(int w){//判断是否上边的都涂完了
int t=dp[w].size();//数上面有几个矩形
for(int i=0;i<t;++i){//分别对每一个矩形判断
if(vis[dp[w][i]]==0) return 0;//有一个没涂上就不符合要求,输出0(╥﹏╥)
}
return 1;//都符合就输出1(*^▽^*)
}
inline void dfs(int cnt,int sum,int cl){//cnt是涂的个数,sum是换的次数,col是上一次的颜色
if(cnt==n){//如果都涂上颜色了就比大小记录最短值
ans=min(ans,sum);
return ;
}
if(sum>=ans) return ;//剪枝,如果没涂完就比答案大了就没必要继续搜了
for(int i=1;i<=n;++i){//找可以涂的矩形枚举
if(vis[i]==0&&check(i)==1){//没涂过并且可以涂
vis[i]=1;//标记涂过
dfs(cnt+1,sum+(cl!=pd[i].col),pd[i].col);//个数++,颜色变了就++,记录颜色
vis[i]=0;//撤销标记回溯
}
}
}
int main(){
cin>>n;//输入
for(int i=1;i<=n;++i){
cin>>pd[i].x1>>pd[i].y1>>pd[i].x2>>pd[i].y2>>pd[i].col;//输入
}
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(i!=j&&pd[i].x1==pd[j].x2&&(pd[i].y2>=pd[j].y1&&pd[i].y1<=pd[j].y2))/*判断两个矩形有无先后顺序(1.下底面对应上顶面;2.左右是否相等)*/ dp[i].push_back(j);//如果有先后顺序就放入数组
}
}
dfs(0,0,0);//深搜
cout<<ans;//输出
return 0;//养成好习惯
}
本题解制作不易,点个赞吧,蟹蟹(✪ω✪)