• 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) 次切割后的各块面积

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

    (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;
    } 
    
  • 相关阅读:
    15个华丽的扁平风格的登录界面设计示例
    12款很酷的使用大头照的国外名片设计作品
    高清壁纸下载:15款精美的2014年元旦桌面壁纸
    Harp – 内置常用预处理器的静态 Web 服务器
    分享245款高质量的图标素材【免费下载】
    经典网页设计:关注用户体验的20个华丽网站
    使用 CSS3 实现超炫的 Loading(加载)动画效果
    你知道网页设计中最常用的15张图片素材吗?
    Koa – 更加强大的下一代 Node.js Web 框架
    Myth – 支持变量和数学函数的 CSS 预处理器
  • 原文地址:https://www.cnblogs.com/zhwer/p/13161327.html
Copyright © 2020-2023  润新知