TOJ 5938: 平板涂色

描述

CE数码公司开发了一种名为自动涂色机(APM)的产品。它能用预定的颜色给一块由不同尺寸且互不覆盖的矩形构成的平板涂色。
为了涂色,APM需要使用一组刷子。每个刷子涂一种不同的颜色C。APM拿起一把有颜色C的刷子,并给所有颜色为C且符合下面限制的矩形涂色:
TOJ 5938: 平板涂色_第1张图片
为了避免颜料渗漏使颜色混合,一个矩形只能在所有紧靠它上方的矩形涂色后,才能涂色。例如图中矩形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

思路:
一个点一个点得搜索显然有点不现实,那就把一个矩形看所一个点,先根据他们之间得坐标来确定矩形a 是否在矩形 b的上面 ,然后进行dfs,考虑到每个节点的分支较多则使用迭代加深搜,每次限定笔刷使用次数来搜索,若此节点的某子节点可以被染色,若颜色与节点相同则不用增加使用次数,反之要增加

代码:

#include
struct node
{
    int x1,y1,x2,y2,color;
};
node rec[16];
bool vis[16],G[16][16],flag;
int n,cnt_r;
bool check(int pos)
{
    for(int i=0;i<n;i++)
        if(G[pos][i]&&!vis[i])return false;
    return true;
}
bool Up(node a,node b)
{
    if((b.x1>=a.x1&&b.x1<a.x2||b.x2<=a.x2&&b.x2>a.x1)&&b.y1>=a.y2)return true;
    return false;
}
void dfs(int pos,int deep,int cnt)
{
    if(deep>cnt_r)return ;
    if(cnt==n)
    {
        flag=true;
        return ;
    }
    for(int i=0;i<n;i++)
    {
        if(!vis[i]&&check(i))
        {
            vis[i]=true;
            int ci;
            if(!deep)ci=1;
            else if(rec[pos].color==rec[i].color)ci=deep;
            else ci=deep+1;
            dfs(i,ci,cnt+1);
            vis[i]=false;
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d%d%d%d%d",&rec[i].y1,&rec[i].x1,&rec[i].y2,&rec[i].x2,&rec[i].color);
    }
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
    {
        if(i!=j&&Up(rec[i],rec[j]))G[j][i]=true;
    }
    for(int i=1;i;i++)
    {
        cnt_r=i;
        dfs(0,0,0);
        if(flag)
        {
            printf("%d\n",i);
            break;
        }
    }
    return 0;
}

若有什么错误,欢迎指正^ _ ^ 。

你可能感兴趣的:(dfs)