时间限制: 1000 ms 内存限制: 65536 KB 提交数: 571 通过数: 302 【题目描述】
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 【来源】No 提交 统计信息 提交记录
#include<iostream>
#include<algorithm>
using namespace std;
int map[101][101],to[101],num[21];
struct block
{
int x1,y1,x2,y2,id;
bool operator <(block &a)const
{
return y2<a.y2;//按照纵坐标排序
}
} go[101];
int n;
void init()
{
cin >>n;
for(int i=1; i<=n; i++)
{
cin >>go[i].y1>>go[i].x1>>go[i].y2>>go[i].x2>>go[i].id;
num[0]=max(num[0],go[i].id);
}
sort(go+1,go+n+1);
}
bool judge(block&g)
{
int he=g.y1;
for(int i=g.x1; i<=g.x2; i++)
if(map[he][i]!=he)//如果上面的区域没被涂色返回false
return false;
return true;
}
int minn=0x3f3f3f3f;
void dfs(int u,int ns,int t)
{
if(t==n)
{
minn=min(minn,ns);
return;
}
if(ns>minn)//大于最小值剪枝
return ;
if(ns>n)//大于最大粉刷次数剪枝
return ;
if(t>n)//粉刷板块数大于总板块数剪枝
return ;
for(int i=1; i<=num[0]; i++){
if(num[i]!=1)//判断颜色i的区域是否涂完了
{
int ret[50];
ret[0]=0;
int s=1;//默认涂完了
for(int j=1; j<=n; j++)
{
if(!to[j]&&(go[j].id==i)&&judge(go[j]))
{
to[j]=1;
ret[++ret[0]]=j;
for(int k=go[j].x1; k<=go[j].x2; k++)
map[go[j].y2][k]=go[j].y2;
}
else if(!to[j]&&go[j].id==i)
{
s=0;//没涂完
}
}
if(ret[0]==0)continue;
num[i]=s;
dfs(i,ns+1,t+ret[0]);
//回溯
for(int k=1; k<=ret[0]; k++)
{
to[ret[k]]=0;
for(int k1=go[ret[k]].x1; k1<=go[ret[k]].x2; k1++)
map[go[ret[k]].y2][k1]=0;
num[i]=0;
}
}
}
}
int main()
{
init();
dfs(0,0,0);
cout <<minn << endl;
}