CF31D | Chocolate(模拟+离线操作)

题目描述

Bob has a rectangular chocolate bar of the size (W*H) . He introduced a cartesian coordinate system so that the point ((0,0)) corresponds to the lower-left corner of the bar, and the point ((W,H)) corresponds to the upper-right corner. Bob decided to split the bar into pieces by breaking it. Each break is a segment parallel to one of the coordinate axes, which connects the edges of the bar. More formally, each break goes along the line (x=x_{c}) or (y=y_{c}) , where (x_{c}) and (y_{c}) are integers. It should divide one part of the bar into two non-empty parts. After Bob breaks some part into two parts, he breaks the resulting parts separately and independently from each other. Also he doesn't move the parts of the bar. Bob made nn breaks and wrote them down in his notebook in arbitrary order. At the end he got (n+1) parts. Now he wants to calculate their areas. Bob is lazy, so he asks you to do this task.

输入格式

The first line contains (3) integers (W) , (H) and (n) ((1<=W,H,n<=100)) — width of the bar, height of the bar and amount of breaks. Each of the following nn lines contains four integers (x_{i,1},y_{i,1},x_{i,2},y_{i,2}) — coordinates of the endpoints of the ii -th break (( 0<=x_{i,1}<=x_{i,2}<=W,0<=y_{i,1}<=y_{i,2}<=H) ,or (x_{i,1}=x_{i,2}),or (y_{i,1}=y_{i,2})Breaks are given in arbitrary order.

It is guaranteed that the set of breaks is correct, i.e. there is some order of the given breaks that each next break divides exactly one part of the bar into two non-empty parts.

输出格式

Output (n+1) numbers — areas of the resulting parts in the increasing order.

——————————————————————————————————————————

题意翻译过来就是在笛卡尔坐标系下有一块长方体巧克力,每次以在巧克力上一条平行于坐标轴的线段进行切割,求 (N) 次切割后的各块面积

CF31D | Chocolate(模拟+离线操作)

数据范围比较小,不去想套什么数据结构了,可以直接离线操作后模拟。

(vis[][][]) 数组标记某小格与上、下、左、右方向的小格是否有间隙(它们之前是否有切割痕迹),如果有,则把对应值附为真

如果是横切,那么会把上下若干个小格分开,即:vis[i][sy-1][0]=vis[i][sy][1]=true;

如果是竖切,那么会把左右若干个小格分开,即:vis[i][sy-1][0]=vis[i][sy][1]=true;

这样操作 (N) 次后,再用 (dfs) 进行连通块的染色,扩展过程中如发现间隙则说明无法从此方向联通

每次 (dfs) 都会得到一个连通块的大小,把这个值存入一个 multiset ,自动排序,直接迭代输出完成

代码如下

#include <bits/stdc++.h>
#define MAXN 107
using namespace std;
int w,h,n,cnt,way[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
bool vis[MAXN][MAXN][4],fl[MAXN][MAXN];
multiset<int> ans;
//up 0 down 1 left 2 right 3
void dfs(int x,int y) {
    cnt++,fl[x][y]=true;
    for (int i=0;i<4;i++) {
        int gx=x+way[i][0],gy=y+way[i][1];
        if (vis[x][y][i] || fl[gx][gy] || gx>=w || gx<0 || gy>=h || gy<0)
            continue;
        dfs(gx,gy);
    }
}
int main() {
    memset(vis,0,sizeof(vis));
    memset(fl,0,sizeof(fl));
    scanf("%d%d%d",&w,&h,&n);
    for (int i=1;i<=n;i++) {
        int sx,sy,tx,ty;
        scanf("%d%d%d%d",&sx,&sy,&tx,&ty);
        if (sx==tx) {
            if (sy>ty) swap(sy,ty);  //保证循环顺序 
            for (int i=sy;i<ty;i++)
                vis[sx-1][i][3]=vis[sx][i][2]=true;
        } 
        else {
            if (sx>tx) swap(sx,tx); //保证循环顺序 
            for (int i=sx;i<tx;i++)
                vis[i][sy-1][0]=vis[i][sy][1]=true; 
        }
    }
    for (int i=0;i<w;i++) {
        for (int j=0;j<h;j++) {
            if (!fl[i][j]) cnt=0,dfs(i,j),ans.insert(cnt);
        }
    }
    for (multiset<int>::iterator it=ans.begin();it!=ans.end();++it) 
        printf("%d ",*it); 
    return 0;
} 

原文链接: https://www.cnblogs.com/zhwer/p/13161327.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    CF31D | Chocolate(模拟+离线操作)

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/357134

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午11:36
下一篇 2023年3月2日 上午11:36

相关推荐