题目链接:http://poj.org/problem?id=1691
题目大意:一块竖的板,由多个矩形组成,现在有多种颜色的刷子,给每个矩形刷上对应的颜色,由于油漆会从高处流下来,所以要求只有与那个矩形直接相邻的上面的矩形被刷了颜色之后,该矩形才能被刷色,求如何给每个矩形涂色,使得切换刷子的次数最少。
代码:
#include<stdio.h>
#include<string.h>
struct Rectangle
{
int x1,y1,x2,y2,color;
int isPainted;
}rec[15];
int recnum,minbrushes,immediateUp[15][15],recUp[15];
void color(int c)//给每个颜色为C的可涂色矩形涂色
{
int i,j;
for(i = 0; i < recnum; i ++) {
if(rec[i].color != c || rec[i].isPainted || recUp[i]) continue;
rec[i].isPainted = 1;
for(j = 0; j < recnum; j ++)
if(immediateUp[i][j]) recUp[j] --;
}
}
void dfs(int brushes)
{
int i,j,k;
int temp_immediateUp[15][15];
int temp_recUp[15];
int temp_isPainted[15];
if(brushes >= minbrushes) return;
for(i = 0; i < recnum; i ++)
if(! rec[i].isPainted) break; /* 已经被涂色 */
if(i == recnum) /* 已经涂完 */
{
minbrushes = brushes;
return;
}
for(i = 0; i < recnum; i ++)
{
if(rec[i].isPainted || recUp[i]) continue; /* 不是位于最上层 (要使次数最少,肯定先涂最上层)或已经被涂色*/
for(j = 0; j < recnum; j ++)
{
temp_recUp[j] = recUp[j];
temp_isPainted[j] = rec[j].isPainted;
for(k = 0; k < recnum; k ++)
temp_immediateUp[j][k] = immediateUp[j][k];
}
color(rec[i].color);
dfs(brushes + 1);
for(j = 0; j < recnum; j ++) {
recUp[j] = temp_recUp[j];
rec[j].isPainted = temp_isPainted[j];
for(k = 0; k < recnum; k ++)
immediateUp[j][k] = temp_immediateUp[j][k];
}
}
}
int main()
{
int i,j,Case;
scanf("%d",&Case);
while(Case--)
{
scanf("%d",&recnum);
for(i=0;i<recnum;i++)
{
scanf("%d%d%d%d%d",&rec[i].x1,&rec[i].y1,&rec[i].x2,&rec[i].y2,&rec[i].color);
rec[i].isPainted = 0;
}
memset(immediateUp, 0, sizeof(immediateUp));
memset(recUp, 0, sizeof(recUp));
for(i=0;i<recnum;i++)
for(j=0;j<recnum;j++)
if(i != j && rec[i].x1 == rec[j].x2 &&
!(rec[j].y2 <= rec[i].y1 || rec[j].y1 >= rec[i].y2))
{
recUp[i] ++; /* there is a rectangle above i */
immediateUp[j][i] = 1; /* j is above i */
}
minbrushes=15;//最多只有15次
dfs(0);
printf("%d\n",minbrushes);
}
return 0;
}