1445:平板涂色

时间限制: 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;
}
链接
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值