1691(dfs + 回溯)

          题目链接: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;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值