【poj 1691】Painting A Board 题意&题解&代码(C++)

63 篇文章 0 订阅

题目链接:

http://poj.org/problem?id=1691

题意:

输入T表示T组数据:
输出n表示有n个矩形:
接下来n行,每行五个数分,y1,x1,y2,x2,c分别表示其左上角坐标和右下角坐标,坐标系按题上所给建立,c表示这个矩形期望得到的颜色。
要求给每个矩形都染上自己期望的颜色,染色规则为:能给某个矩形染色当且仅当此矩形上方的所有矩形均已染色,染色时一旦染色必须是给整块矩形染色,问最少更换几次颜色可以涂完所有的矩形。

题解:

读完题意发现,一个矩形能够控制的矩形是它正下方的紧挨着它的矩形,每次必须先涂没有被控制的矩形,似乎想到了拓扑排序,至于让换颜色的次数最小,观察数据范围n小于15,唉,不用纠结,果断暴力涂色。

代码:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<vector>
#include<string.h>
using namespace std;
struct node{
    int x1,x2,y1,y2;
    int id,c;
}ar[21];
vector<int>lin[21];
int ans,n,T,in[21],vis[21];
void dfs(int tot,int step,int nowc)
{
    if (step>=ans) return ;
    if (tot==n)
    {
        ans=step;
        return ;
    }
    for (int i=1;i<=n;i++)
    if (in[i]==0&&vis[i]==0)
    {
        for (int j=0;j<lin[i].size();j++)
        in[lin[i][j]]--;
        vis[i]=1;
        if (nowc==ar[i].c)
        dfs(tot+1,step,nowc);
        else
        dfs(tot+1,step+1,ar[i].c);
        vis[i]=0;
        for (int j=0;j<lin[i].size();j++)
        in[lin[i][j]]++;
    }
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        ans=999999;
        for (int i=1;i<=n;i++)
        {
            scanf("%d%d%d%d%d",&ar[i].y1,&ar[i].x1,&ar[i].y2,&ar[i].x2,&ar[i].c);
            ar[i].id=i;
            lin[i].clear();
            in[i]=0;vis[i]=0;
        }
        //建图,即建立控制关系
        for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
        if (ar[j].x1<ar[i].x2&&ar[j].x2>ar[i].x1&&ar[j].y1==ar[i].y2)
        {   
            lin[i].push_back(j);
            in[j]++;
        }
        for (int i=1;i<=n;i++)
        if (in[i]==0&&vis[i]==0)
        {
            vis[i]=1;
                    for (int j=0;j<lin[i].size();j++)
                    in[lin[i][j]]--;
            dfs(1,1,ar[i].c);
            vis[i]=0;
                    for (int j=0;j<lin[i].size();j++)
                    in[lin[i][j]]++;
        }
        printf("%d\n",ans);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值