poj 1691 Painting A Board

Painting A Board
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 3794 Accepted: 1876

Description

The CE digital company has built an Automatic Painting Machine (APM) to paint a flat board fully covered by adjacent non-overlapping rectangles of different sizes each with a predefined color. 

To color the board, the APM has access to a set of brushes. Each brush has a distinct color C. The APM picks one brush with color C and paints all possible rectangles having predefined color C with the following restrictions: 
To avoid leaking the paints and mixing colors, a rectangle can only be painted if all rectangles immediately above it have already been painted. For example rectangle labeled F in Figure 1 is painted only after rectangles C and D are painted. Note that each rectangle must be painted at once, i.e. partial painting of one rectangle is not allowed. 
You are to write a program for APM to paint a given board so that the number of brush pick-ups is minimum. Notice that if one brush is picked up more than once, all pick-ups are counted. 

Input

The first line of the input file contains an integer M which is the number of test cases to solve (1 <= M <= 10). For each test case, the first line contains an integer N, the number of rectangles, followed by N lines describing the rectangles. Each rectangle R is specified by 5 integers in one line: the y and x coordinates of the upper left corner of R, the y and x coordinates of the lower right corner of R, followed by the color-code of R. 
Note that: 
  1. Color-code is an integer in the range of 1 .. 20. 
  2. Upper left corner of the board coordinates is always (0,0). 
  3. Coordinates are in the range of 0 .. 99. 
  4. N is in the range of 1..15.

Output

One line for each test case showing the minimum number of brush pick-ups.

Sample Input

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

Sample Output

3

Source

提示

题意:

一面墙上要涂满颜色,且涂满颜色的部分都是矩阵,矩阵大小以左上角和右下角坐标的形式给出,最多有n(1<=n<=15)块,坐标范围是[0,99](坐标以[y,x]的形式给出),颜色编号从1到20。涂颜色的规则:为了防止刚刷上的颜料会往下流并它下面另一种颜色混合,所以涂颜色的时候上方必须已涂颜色或者与要涂的颜色相同。

对于刷子的使用:当前刷了颜料A后如果以后还刷颜料A可以不换刷子,否则要换。并且之前刷过颜料A,但现在刷过颜料B时,依然需要重新刷一把刷子。求出最少需要多少刷子才能完成任务。

思路:

坐标较小我们可以用二维数组来维护墙的状态,假设数组mark[100][100]全为0,矩阵左上角坐标sx,sy,右下角坐标tx,ty。先初始化mark[0][0~99]全为1,表示左上角坐标sy为0的矩阵可以涂了,因为它们是最上面的部分。之后利用dfs+回溯来搜索最优解:

判断(sx,sy)~(tx,sy)这条线上是否都做过标记,如果都有说明上面已被涂满颜色,当前矩阵满足条件,之后对(sx,ty)~(tx,ty)做上标记。

示例程序

Source Code

Problem: 1691		Code Length: 1609B
Memory: 424K		Time: 0MS
Language: G++		Result: Accepted
#include <stdio.h>
#include <string.h>
struct
{
    int sx,sy,tx,ty,kind;
}a[15];
int num,v[15],mark[100][100];	//num:所需刷子数,v[]:访问节点记录,mark[][]:维护墙的状态
int judge(int pos)			//是否满足被涂的条件
{
    int i;
    for(i=a[pos].sx;a[pos].tx>=i;i++)
    {
        if(mark[a[pos].sy][i]==0)
        {
            return 0;
        }
    }
    return 1;
}
void dfs(int pos,int deep,int ans,int n)
{
    int i,i1;
    if(ans==num)			//没有比当前num更小的情况
    {
        return;
    }
    if(deep==n)			//全都已涂完
    {
        num=ans;
        return;
    }
    for(i=0;n>i;i++)
    {
        if(v[i]==0&&judge(i)==1)
        {
            v[i]=1;
            for(i1=a[i].sx;a[i].tx>=i1;i1++)
            {
                mark[a[i].ty][i1]=1;
            }
            if(pos!=-1&&a[pos].kind==a[i].kind)		//如果上一个的颜色和当前相同不需要换刷子
            {
                dfs(i,deep+1,ans,n);
            }
            else
            {
                dfs(i,deep+1,ans+1,n);
            }
            for(i1=a[i].sx;a[i].tx>=i1;i1++)		//墙状态回溯
            {
                mark[a[i].ty][i1]=0;
            }
            v[i]=0;			//节点回溯
        }
    }
}
int main()
{
    int m,i,n,i1;
    scanf("%d",&m);
    for(i=1;m>=i;i++)
    {
        scanf("%d",&n);
        for(i1=0;n>i1;i1++)
        {
            scanf("%d %d %d %d %d",&a[i1].sy,&a[i1].sx,&a[i1].ty,&a[i1].tx,&a[i1].kind);
        }
        num=n;			//初始化最大所需刷子数为矩阵个数
        memset(v,0,sizeof(v));
        memset(mark,0,sizeof(mark));
        for(i1=0;100>i1;i1++)
        {
            mark[0][i1]=1;
        }
        dfs(-1,0,0,n);
        printf("%d\n",num);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值