POJ 1691 Painting A Board

本文介绍了一种使用深度优先搜索(DFS)实现的拓扑排序算法来解决矩形区域涂色问题的方法。该算法通过构建矩形之间的依赖关系图,并利用DFS遍历寻找入度为0的节点,以此来确定最小的涂色次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 /*
DFS拓扑排序,要注意局部状态的记录
建图的方法:如果矩形a是紧邻b上方的矩形,则graph[a][b] = true
DFS时,每次记录上一次用到的刷子的颜色,然后从当前记忆保存的graph中
寻找入度为0的矩形,如果其颜色不等于上一次用到的刷子的颜色,则总数+1,
然后从新的矩形中清除掉以这个矩形为端点的变,继续下一次DFS
*/
#include <iostream>
#define MAX_N 15
using namespace std;

bool graph[MAX_N + 1][MAX_N + 1];
int n, minNum;
struct rec
{
    int x1, y1, x2, y2;
    int color;
}recs[MAX_N + 1];

bool onup(const rec &c1, const rec &c2)
{
    bool check1 = c1.y2 == c2.y1;
    bool check2 = (c2.x1 >= c1.x1 && c2.x1 < c1.x2) || (c2.x2 <= c1.x2 && c2.x2 > c1.x1);
    return check1 && check2;
}
//graph[i][i]有特殊用途,记忆矩形i是否被刷过,如果graph[i][i] = true则没有被刷过
void topnology(int curNum, int lastColor, bool graph[][MAX_N + 1])
{
    if(curNum > minNum) return;
    int i, j, k;
    bool goon = false;
    for(i = 1; i <= n; i++)
    {
        if(!graph[i][i]) continue;
        bool can = true;
        for(j = 1; j <= n && can; j++)
            if(i != j && graph[j][i]) can = false;
        if(can)
        {
            goon = true;
            bool tempG[MAX_N + 1][MAX_N + 1];
            for(j = 1; j <= n; j++)
            {
                for(k = 1; k <= n; k++)
                {
                    if(j == i || k == i) tempG[j][k] = false;
                    else tempG[j][k] = graph[j][k];
                }
            }
            tempG[i][i] = false;
            int newNum = (lastColor == recs[i].color) ? curNum : curNum + 1;
            topnology(newNum, recs[i].color, tempG);
        }
    }
    if(!goon)
    {
        if(curNum < minNum)
            minNum = curNum;
    }
}
int main()
{
    int caseNum, i, j;
    scanf("%d", &caseNum);
    while(caseNum--)
    {
        scanf("%d", &n);
        memset(graph, 0, sizeof(graph));
        for(i = 1; i <= n; i++)
        {
            graph[i][i] = true;
            scanf("%d%d%d%d%d", &recs[i].y1, &recs[i].x1, &recs[i].y2, &recs[i].x2, &recs[i].color);
            for(j = 1; j < i; j++)
            {
                if(onup(recs[i], recs[j])) graph[i][j] = true;
                if(onup(recs[j], recs[i])) graph[j][i] = true;
            }
        }
        minNum = INT_MAX;
        topnology(0, -1, graph);
        printf("%d/n", minNum);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值