习题5-12 地图查询(Do You Know The Way to San Jose?,ACM/ICPC World Finals1997,UVa511)

原题链接:https://vjudge.net/problem/UVA-511
分类:STL综合
备注:复杂模拟
前言:搞这个翻译纯属是闲,翻译完才知道明明紫书说的很清楚了!
补充:尼玛这要死么,我少打了个字母找了超久的错误!

题目

(辅以百度)翻译:
现在的互联网提供了不同的交互式地图工具,这使得使用者可以看到显示大块地理区域的概括性地图,也可以在一个更多细节的地图上“拉近镜头"到某条特定的街道,有时甚至是某个特定建筑。譬如,城市圣何塞可能出现在一份描述加利福尼亚州的地图上,或者是一份描述圣克拉拉谷地县的地图上,还可能是在一份详细的街道地图上。
假设你有很大的矩形地图集并且你希望设计一个浏览工具,用来处理一系列的对地图某地点位置的请求,这些请求是建立在不同的地图详细级别上的。各种地点会用它们的名字来表示。每个地点有单独的实数坐标(x,y)。各种地图是也是独一无二的,它们用地图识别名做了标记,并且被两对实数坐标(x1,y1),(x2,y2)——用以表示地图的相对的两个角。所有地图的边界都平行于标准的笛卡尔坐标系的x轴和y轴。一份地图和一个地点可能有相同的名字。一份地图的纵横比(紫书上说长宽比)指的是该地图的高度闭上宽度(宽度用x轴测量,高度用y轴测量)。
一份地图的详细级别可以用该地图表示的矩形面积来大致估算,换句话说,认为一份地图描述的地理面积越小,则包括越多的细节。一份地图可能部分重叠于另一份地图。如果一个地点(x,y)同时在两份或者多份地图上有相同的面积,首选的地图(在相同的详细级别上)是那份该地点最接近地图中心的地图。如果有两份都包括该地点的重叠地图上,该地点到两份地图的中心是等距的,那么更优的选择(在相同的详细级别上)是纵横比更接近0.75的地图。如果仍有多个选择,那么更优的地图是该地点距离地图右下角最远的地图(该算法是为了最小化需要在用户浏览器窗口中滚动)。最后,如果这里仍然有多个选择,那么更优先的是包含最小x坐标的地图。
一个给定地点可获得的最大详细级别是包含该地点的地图的最大不同面积数。显然,不同的地点可能有不同的最大详细等级。对于该地点有某地图详细级别为 i i ,说明在清晰地包括该地点的地图的最大集合中,该地图的面积是第 i i 大的。因此,对于该地点的详细级别为1的地图是最不详细的(最大面积),而包括该地点的地图中详细级别最高的是最详细的(最小面积)。

输入

输入文件包括一系列的地图,地点以及请求;它被组织成以下形式:

  • 单词"MAPS",完全由大写字母组成且占据一行,介绍一系列的地图,地图数为一份或多份。在该标题之下(应该是指"MAPS"是标题),每份地图用单独的一行表示,该行包括地图的名字(一个由字母组成的字符串,没有前导、尾随或嵌入空格)和两个实数坐标对——x1 ,y1, x2 ,y2——表示地图的对角。
  • 单词"LOCATIONS",完全由大写字母组成且占据一行,介绍一系列的地点,地点数为一个或多个。在该标题之下,每份地图用单独的一行表示,该行包括地点的名字(一个由字母组成的字符串,没有前导、尾随或嵌入空格)和一个实数坐标对——x,y——表示该地的中心。
  • 单词"REQUESTS",完全由大写字母组成且占据一行,介绍一系列的请求,请求数为零个或多个。在该标题之下,每个请求用单独的一行描述,该行包括一个地点的名字(一个由字母组成的字符串,没有前导、尾随或嵌入空格)以及一个正整数,该正整数表示所要查找的地图的详细等级。
  • 单词"WORD",完全由大写字母组成且占据一行,结束输入文件。

在请求之前的所有地图和地点数据都是有效的。没有完全一样的重复地图。处理一个有效请求的结果是地图的名字,该地图包含了给定的地点且属于给定的详细等级(用上文描述的平局决胜的规则)。可能出现无效请求,即请求未知的地点名字,地点未出现在任何地图上,或者详细等级超过了地图的最大详细等级。
以下的例子应解释所有的这些定义:

输出

每个请求都必须响应到输出。如果请求有效,显示满足请求的地图的名字。如果地点不在地图上,则显示一条信息说明该结果。如果地点在地图上,但是要求的详细等级太大了,则显示合法的详细等级中最大的地图的名字。

Sample Input

MAPS
BayArea -6.0 12.0 -11.0 5.0
SantaClara 4.0 9.0 -3.5 2.5
SanJoseRegion -3.0 10.0 11.0 3.0
CenterCoast -5.0 11.0 1.0 -8.0
SanMateo -5.5 4.0 -12.5 9.0
NCalif -13.0 -7.0 13.0 15.0
LOCATIONS
Monterey -4.0 2.0
SanJose -1.0 7.5
Fresno 7.0 0.1
SanFrancisco -10.0 8.6
SantaCruz -4.0 2.0
SanDiego 13.8 -19.3
REQUESTS
SanJose 3
SanFrancisco 2
Fresno 2
Stockton 1
SanDiego 2
SanJose 4
SantaCruz 3
END

看输入数据可以明白(x1,y1),(x2,y2)是没有顺序的。只知道是两个相对的角,两种可能都有。

Sample Output

SanJose at detail level 3 using SanJoseRegion
SanFrancisco at detail level 2 using BayArea
Fresno at detail level 2 no map at that detail level; using NCalif
Stockton at detail level 1 unknown location
SanDiego at detail level 2 no map contains that location
SanJose at detail level 4 using SantaClara
SantaCruz at detail level 3 no map at that detail level; using CenterCoast

可以看出第三个输出是要求详细等级过大的情况,第四个输出为请求未知地点的情况,第五个输出为地图不包含地点的情况。

代码如下:

#include<iostream>
#include<string>
#include<vector>
#include<cmath>
#include<map>
#include<algorithm>
using namespace std;
double px, py;
struct MAPS {
	string name;
	double area;//面积
	double ratio;//长宽比
	double x1, y1, x2, y2;//对角数据,使x2<x1,y2<y1更方便地图的筛选
	double cx, cy;
	MAPS(string s, double _x1, double _y1, double _x2, double _y2) :
		name(s), x1(_x1), y1(_y1), x2(_x2), y2(_y2) {
		if (x1 < x2)swap(x1, x2);
		if (y1 < y2)swap(y1, y2);
		cx = (x1 + x2) / 2.0;
		cy = (y1 + y2) / 2.0;
		area = (x1 - x2) * (y1 - y2);
		ratio = (y1 - y2) / (x1 - x2);
	}
};
struct LOCATIONS {
	string name;
	double x, y;
};
bool cmp(const MAPS& a, const MAPS& b) {
	if (a.area != b.area)return a.area < b.area;
	double adis = pow(px - a.cx, 2) + pow(py - a.cy, 2);
	double bdis = pow(px - b.cx, 2) + pow(py - b.cy, 2);
	if (adis != bdis)return adis < bdis;
	double ar = fabs(a.ratio - 0.75), br = fabs(b.ratio - 0.75);
	if (ar != br)return ar < br;
	double adis2 = pow(py - a.y2, 2) + pow(px - a.x1, 2);
	double bdis2 = pow(py - b.y2, 2) + pow(px - b.x1, 2);
	if (adis2 != bdis2)return adis2 > bdis2;
	return a.x2 < b.x2;
}
bool cmp2(const double& a, const double& b) {
	return a > b;
}
int main(void) {
	vector<MAPS>maps;
	vector<LOCATIONS>loc;
	map<string, int>id;
	string s; cin >> s;
	while (cin >> s) {
		if (s == "LOCATIONS")break;
		double x1, y1, x2, y2;
		cin >> x1 >> y1 >> x2 >> y2;
		maps.push_back(MAPS(s, x1, y1, x2, y2));
	}
	while (cin >> s) {
		if (s == "REQUESTS")break;
		double x, y;
		cin >> x >> y;
		if (!id.count(s)) {
			loc.push_back(LOCATIONS{ s,x,y });
			id[s] = loc.size() - 1;
		}
	}
	while (cin >> s) {
		if (s == "END")break;
		int level;
		cin >> level;
		cout << s << " at detail level " << level << ' ';
		if (!id.count(s)) {
			cout << "unknown location\n";
			continue;
		}
		else px = loc[id[s]].x, py = loc[id[s]].y;
		vector<MAPS>tmp;
		vector<double>area;
		for (int i = 0; i < maps.size(); i++) {//x2<x1
			if (maps[i].x1 < px || maps[i].x2 > px)continue;
			if (maps[i].y1 < py || maps[i].y2 > py)continue;
			tmp.push_back(maps[i]);
			area.push_back(maps[i].area);
		}
		if (tmp.empty()) {
			cout << "no map contains that location\n";
			continue;
		}
		sort(tmp.begin(), tmp.end(), cmp);
		int lev = unique(area.begin(), area.end()) - area.begin();
		if (lev < level)
			cout << "no map at that detail level; using " << tmp[0].name << '\n';
		else {
			cout << "using ";
			for (int i = 0; i < tmp.size(); i++) {
				if (i && tmp[i].area != tmp[i - 1].area)lev--;
				if (lev == level) {
					cout << tmp[i].name << '\n';
					break;
				}
			}
		}
	}
	return 0;
}
发布了104 篇原创文章 · 获赞 97 · 访问量 4515

猜你喜欢

转载自blog.csdn.net/TK_wang_/article/details/104784973