USACO 6.2.3 Shaping Regions

本文介绍了一个关于矩形覆盖的问题,通过使用C++实现了一种解决方案。该方案利用递归计算每个矩形被覆盖的面积,并最终统计每种颜色覆盖的总面积。

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

http://train.usaco.org/usacoprob2?a=NaWWtjt80VA&S=rect1

题目大意:在一个A*B的坐标区域内(A,B <= 10000)从底向上覆盖N(N <= 1000)个不同颜色(用数字表示1~2500)的矩形,求最后能够被看到的颜色和他们各自覆盖的面积(桌布底色为1,需要考虑)




很直观的就把他和之前一道矩形覆盖的题目联系了起来,用一个链表(数组)按次序存储然后对每一矩形先算面积,再上浮并分裂计算其被覆盖的面积,原本以为会RE,毕竟我用的是递归计算,在计算底层是得要递归N次,但没想到竟然通过了,真是难以置信,那这么看来这道题比之前那道反而简单,因为他连移动都不需要所以直接用数组就行

看了官方题解之后发现其实可以改成在插入每一个矩形时将下方矩形分裂,这样就不会有RE的风险,而且虽然在最坏情况下每一次分裂都会产生三个新矩形(4-1),但是新产生的四个小矩形再下次分裂时不可能再各自产生四个(最多就总共多产生四个)。不过这样一来就要用链表存储矩形,遍历链表的时候也要注意下一个要跳过刚刚新分裂出的矩形

/*
ID: frontie1
TASK: rect1
LANG: C++
*/
#include <iostream>
#include <cstdio>

using namespace std;

const int INFI = 0x3f3f3f3f;

struct rectangle
{
    int upp;
    int dow;
    int lef;
    int rig;
    int color;

    rectangle(int u = INFI, int d = 0, int l = 0, int r = INFI, int c = 0):upp(u), dow(d), lef(l), rig(r), color(c){};

    int overlap(const rectangle &obj)
    {
        int u = min(upp, obj.upp);
        int d = max(dow, obj.dow);
        int l = max(lef, obj.lef);
        int r = min(rig, obj.rig);

        if(u <= d || r <= l) return 0;
        else return ((u-d) * (r-l));
    }

    int area()
    {
        return ((upp-dow) * (rig-lef));
    }
};

int N;
rectangle arr[1010];
int area[2505];

int covered(rectangle obj, int num)
{
    if(num > N) return 0;
    rectangle tar = arr[num];

    int output = obj.overlap(tar);
    if(output == 0) output += covered(obj, num+1);
    else{
        rectangle tem;
        if(tar.lef > obj.lef) output += covered(rectangle(obj.upp, obj.dow, obj.lef, tar.lef, obj.color), num+1);
        if(tar.rig < obj.rig) output += covered(rectangle(obj.upp, obj.dow, tar.rig, obj.rig, obj.color), num+1);
        if(tar.upp < obj.upp) output += covered(rectangle(obj.upp, tar.upp, max(tar.lef, obj.lef), min(tar.rig, obj.rig), obj.color), num+1);
        if(tar.dow > obj.dow) output += covered(rectangle(tar.dow, obj.dow, max(tar.lef, obj.lef), min(tar.rig, obj.rig), obj.color), num+1);
    }
    return output;
}

int main()
{
    freopen("rect1.in", "r", stdin);
    freopen("rect1.out", "w", stdout);

    cin >> arr[0].rig >> arr[0].upp;
    arr[0].color = 1;

    cin >> N;

    for(int i = 1; i <= N; ++i){
        cin >> arr[i].lef >> arr[i].dow >> arr[i].rig >> arr[i].upp >> arr[i].color;
    }

    for(int i = 0; i <= N; ++i){
        area[arr[i].color] += arr[i].area();
        area[arr[i].color] -= covered(arr[i], i+1);
    }

    for(int i = 1; i <= 2500; ++i){
        if(area[i] != 0) cout << i << ' ' << area[i] << endl;;
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值