POJ 1691 Painting A Board

题目大意:

墙上有一块区域被分成了n个矩形,每个矩形要涂上各自的颜色。为了保证完美要求这一块区域可以进行涂色的条件是它上方的所有区域都已经涂好颜色,这样就不会有后续的操作影响这块区域的颜色。但是如果两块区域颜色不同就要换涂颜色用的刷子。问最少需要换几次。


解题思路:

区域涂色的大体次序是由拓扑排序决定的,当有多个区域在同一层次时需要枚举这些区域来保证换刷子的次数最小。



下面是代码:

#include <stdio.h>
#include <stdlib.h>

struct node1
{
    int x1,y1,x2,y2,c,status;
} node[100];
int cnt,min1,n,edgecnt;
struct edge1
{
    int u,v,next;
} edge[100];
int head[20];
void addedge(int u,int v)
{
    edge[edgecnt].v=v;
    edge[edgecnt].u=u;
    edge[edgecnt].next=head[u];
    head[u]=edgecnt++;
    node[v].status++;
}
int min(int a,int b)
{
    if(a>b)a=b;
    return a;
}
void dfs(int num,int col)
{
    //printf("%d %d %d\n",num,col,cnt);
    if(num==0)
    {
        min1=min(min1,cnt);
        return ;
    }
    for(int i=0; i<n; i++)
    {
        if(node[i].status==0)
        {
            int p=head[i];
            while(p!=-1)
            {
             node[edge[p].v].status--;
                p=edge[p].next;
            }
            if(col!=node[i].c)cnt++;
            node[i].status=-1;
            dfs(num-1,node[i].c);
            node[i].status=0;
            p=head[i];
            while(p!=-1)
            {
                node[edge[p].v].status++;
                p=edge[p].next;
            }
            if(col!=node[i].c)cnt--;
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0; i<n; i++)
        {
            scanf("%d%d%d%d%d",&node[i].y1,&node[i].x1,&node[i].y2,&node[i].x2,&node[i].c);
            node[i].status=0;
            head[i]=-1;
        }
        edgecnt=0;
        min1=10000000;
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<n; j++)
            {
                if(node[i].y2==node[j].y1&&!(node[j].x1>node[i].x2||node[i].x1>node[j].x2))
                {
                    addedge(i,j);
                }
            }
        }
        cnt=0;
        dfs(n,-1);
        printf("%d\n",min1);
    }
    return 0;
}


转载于:https://www.cnblogs.com/lin375691011/p/3996658.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值