平板涂色
题目描述
CE 数码公司开发了一种名为自动涂色机(APM)的产品。它能用预定的颜色给一块由不同尺寸且互不覆盖的矩形构成的平板涂色。
为了涂色,APM 需要使用一组刷子。每个刷子涂一种不同的颜色 C i C_i Ci 。APM 拿起一把有颜色 C i C_i Ci 的刷子,并给所有颜色为 C i C_i Ci 且符合下面限制的矩形涂色:
为了避免颜料渗漏使颜色混合,一个矩形只能在所有紧靠它上方的矩形涂色后,才能涂色。例如图中矩形 F F F 必须在 C C C 和 D D D 涂色后才能涂色。注意,每一个矩形必须立刻涂满,不能只涂一部分。
写一个程序求一个使 APM 拿起刷子次数最少的涂色方案。注意,如果一把刷子被拿起超过一次,则每一次都必须记入总数中。
输入格式
第一行为矩形的个数 N N N。下面有 N N N 行描述了 N N N 个矩形。每个矩形有 5 5 5 个整数描述,左上角的 y y y 坐标和 x x x 坐标,右下角的 y y y 坐标和 x x x 坐标,以及预定颜色。
平板的左上角坐标总是 ( 0 , 0 ) (0,0) (0,0)。
输出格式
一个整数,表示拿起刷子的最少次数。
样例 #1
样例输入 #1
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
样例输出 #1
3
提示
1 ≤ C i ≤ 20 1\le C_i \le 20 1≤Ci≤20, 0 ≤ x i , y i ≤ 99 0 \le x_i,y_i \le 99 0≤xi,yi≤99, 1 ≤ N ≤ 16 1\le N \le 16 1≤N≤16。
#include<bits/stdc++.h>
using namespace std;
int n,num,ans=0x3f3f3f;
int m[10000][10000];
struct node
{
int lx,rx,ly,ry,c,vis;
}a[21];
void add(int x)//涂色
{
for(int j=a[x].lx+1;j<=a[x].rx;j++)
for(int k=a[x].ly+1;k<=a[x].ry;k++)
m[j][k]=0;
}
void del(int x)//清除颜色
{
for(int j=a[x].lx+1;j<=a[x].rx;j++)
for(int k=a[x].ly+1;k<=a[x].ry;k++)
m[j][k]=a[x].c;
}
int pd(int x)//判断是否下一个矩形颜色相同
{
for(int i=a[x].ly+1;i<=a[x].ry;i++)
if(m[a[x].lx][i]!=0) return 0;
return 1;
}
void dfs(int now,int sum,int cnt)
{
if(sum>ans) return;//剪枝,只存最优解
if(cnt==n)//到达解答层
{
ans=sum;//更新答案
return;
}
for(int i=1;i<=n;i++)
{
if(!a[i].vis&&pd(i))
{
if(a[i].c==a[now].c&&pd(i))//如果颜色相同
{
a[i].vis=1;//标记
add(i);
dfs(i,sum,cnt+1);//不用再提刷子
a[i].vis=0;//回溯
del(i);
}
if(a[i].c!=a[now].c&&pd(i))//如果颜色不同
{
a[i].vis=1;//标记
add(i);
dfs(i,sum+1,cnt+1);//再提一次刷子
a[i].vis=0;//回溯
del(i);
}
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].lx>>a[i].ly>>a[i].rx>>a[i].ry>>a[i].col;
a[i].vis=0;
for(int j=a[i].lx+1;j<=a[i].rx;j++)
for(int k=a[i].ly+1;k<=a[i].ry;k++)
m[j][k]=a[i].c;//存颜色
}
for(int i=1;i<=n;i++)
{
if(!a[i].lx&&!a[i].vis)
{
a[i].vis=1;
add(i);
dfs(i,1,1);//从第一个矩形开始
a[i].vis=0;
del(i);
}
}
cout<<ans;
}
1.用vis数组判断是否涂色
2.pd函数判断是否下方紧靠的矩形于上面的颜色相同,如果相同,就提一次刷子
3.如果目前提刷子的次数sum大于以前存的次数ans,剪枝