[离散化] Urban Elevations Uva211

题目描述

An elevation of a collection of buildings is an orthogonal projection of the buildings onto a vertical plane. An external elevation of a city would show the skyline and the faces of the “visible” buildings of the city as viewed from outside the city from a certain direction. A southern elevation shows no sides;it shows the perfectly rectangular faces of buildings or parts of faces of buildings not obstructed on the south by taller buildings. For this problem, you must write a program that determines which buildings of a city are visible in a southern elevation.

For simplicity, assume all the buildings for the elevation are perfect rectangular solids, each with two sides that run directly east-west and two running directly north-south. Your program will find the buildings that appear in a southern elevation based on knowing the positions and heights of each city building. That data can be illustrated by a map of the city as in the diagram on the left below. The southern elevation for that city is illustrated in the diagram on the right.
这里写图片描述
input
Input for your program consists of the numeric description of maps of several cities. The first line of each map contains the number of buildings in the city (a non-negative integer less than 101). Each subsequent line of a map contains data for a single building — 5 real numbers separated by spaces in the following order:

  • x-coordinate of the southwest corner
  • y-coordinate of the southwest corner
  • width of the building (length of the south side)
  • depth of the building (length of the west side)
  • height of the building

Each map is oriented on a rectangular coordinate system so that the positive x-axis points east and the positive y-axis points north. Assume that all input for each map corresponds to a legitimate map (the number of buildings is the same as the number of subsequent lines of input for the map; no two buildings in a single map overlap). Input is terminated by the number 0 representing a map with no buildings.
output
Buildings are numbered according to where their data lines appear in the map’s input data — building#1 corresponding to the first line of building data, building #2 data to the next line, and building #n to the nth line of building data for that map. (Buildings on subsequent maps also begin their numbering with 1.)

For each map, output begins with line identifying the map (map #1, map #2, etc.) On the next line the numbers of the visible buildings as they appear in the southern elevation, ordered south-to-north, west-to-east. This means that if building n and building m are visible buildings and if the southwest corner of building n is west of the southwest corner of building m, then number n is printed before number m. If building n and building m have the same x-coordinate for their southwest corners and if building n is south of building m, then the number n is printed before the number m.

For this program, a building is considered visible whenever the part of its southern face that appears in the elevation has strictly positive area. One blank line must separate output from consecutive input records.

题解

这题代码是直接搬刘汝佳老师的,但让我初步认识了离散化。这里总结一下自己对离散化的理解。

通常如果要用暴力模拟的方法解题,会增加许多附加信息。如,在解该题时我也曾想将所有的建筑“画在一个网格中”,但是题目告诉坐标值都是实数且没有最大值。这样就无法在有限空间(比如一个定长数组中)保存信息。

如果可以保存信息,那按照这种方法会多保存一些信息。空间复杂度和时间复杂度也会相应提高。比如该题保存后除了保存起始点的3个坐标和其对应边长度外,还会保存每个点的具体信息。当然,该题中坐标是实数,无法这样表示。

而使用离散化,则着重保存的是关键点信息及其相对关系。这里可以联系另一个离散化题目。这类离散化方法都有一下几个步骤:

  1. 保存关键点信息
  2. 排序、去重,获得相对位置信息
  3. 使用离散化数据处理问题

该题中有如下几步实现:

for(int i = 0; i<n; i++){
            scanf("%lf%lf%lf%lf%lf", &b[i].x, &b[i].y, &b[i].w, &b[i].d, &b[i].h);
            b[i].No = i+1;
            x[i*2] = b[i].x;x[i*2+1] = b[i].x + b[i].w;
        }
        sort(b, b+n);
        sort(x, x+2*n);
        int m = unique(x, x+2*n) - x;

AC代码

#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn = 100 + 5;

struct Building {
    int No;
    double x, y, w, d, h;
    bool operator < (const Building& rhs) const {
        return x < rhs.x || (x == rhs.x && y < rhs.y);
    }
} b[maxn];
int n;
double x[maxn*2];

bool cover(int i, double mx){
    return b[i].x <= mx && b[i].x+b[i].w >=mx;
}

bool visible(int i, double mx){
    if(!cover(i, mx)) return false;
    for(int k = 0; k<n; k++)
        if(b[k].y < b[i].y && b[k].h>=b[i].h && cover(k, mx)) return false;
    return true;
}

int main(){
    int kase = 0;

    while(scanf("%d", &n)==1 && n){
        for(int i = 0; i<n; i++){
            scanf("%lf%lf%lf%lf%lf", &b[i].x, &b[i].y, &b[i].w, &b[i].d, &b[i].h);
            b[i].No = i+1;
            x[i*2] = b[i].x;x[i*2+1] = b[i].x + b[i].w;
        }
        sort(b, b+n);
        sort(x, x+2*n);
        int m = unique(x, x+2*n) - x;

        if(kase++) printf("\n");
        printf("For map #%d, the visible buildings are numbered as follows:\n%d", kase, b[0].No);

        for(int i = 1; i<n; i++){
            bool vis = false;
            for(int j = 0; j < m-1; j++)
                if(visible(i, (x[j]+x[j+1])/2)){vis=true; break;}
            if(vis) printf(" %d", b[i].No);
        }
        printf("\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一份Python代码,可实现河流大断面的计算和可视化处理。其中包括多个用户输入起点距与河底高程,用列表储存,以及用河底高程和起点距计算。当河床有突出的一块时,计算时采用分块相加的办法。 ```python import matplotlib.pyplot as plt # 获取用户输入的起点距和河底高程 distances = [] bed_elevations = [] while True: distance = input('请输入起点距(按回车键结束):') if distance == '': break bed_elevation = input('请输入河底高程:') distances.append(float(distance)) bed_elevations.append(float(bed_elevation)) # 计算断面面积 area = 0 for i in range(len(distances) - 1): distance_diff = distances[i + 1] - distances[i] bed_elevation_avg = (bed_elevations[i + 1] + bed_elevations[i]) / 2 area += distance_diff * bed_elevation_avg # 可视化处理 fig, ax = plt.subplots() ax.plot(distances, bed_elevations, '-o') ax.set_xlabel('距离(米)') ax.set_ylabel('高程(米)') ax.fill_between(distances, bed_elevations, color='blue', alpha=0.2) ax.set_title('河流大断面') plt.text(max(distances) * 0.75, max(bed_elevations) * 0.5, f'面积:{area:.2f} 平方米', fontsize=12) plt.show() ``` 运行代码后,会提示输入起点距和河底高程。用户可以输入任意多个起点距和对应的河底高程,当输入空行时,输入过程结束,代码开始计算断面面积并绘制可视化处理的图形。 图形中,蓝色的线段代表河床的高程变化,蓝色填充区域代表河流大断面的面积。图形的标题中会显示河流大断面的面积值。用户可以根据自己的需求进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值