map<string,map<double,vector<string>,greater<double>>>是每一个地点到包含这些地点的地图的映射。第二个map是地图面积到地图的映射,其中传入了一个greater<double>来讲这些面积按照从大到下的顺序排序,对应detail level 从小到大。vector<string> 保存了面积相同的地图,在程序中,我定义了一个compare函数来将这些面积相同的地图按照题目要求排序,这样,vector[0]就是所要找的地图。
另外需注意的是,题目只说了输入的表示地图的两个点是对角线上的两个点,但并未说是哪一条对角线。
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
#include <cmath>
#include <functional>
using namespace std;
struct Map{
Map() = default;
Map(double, double, double, double);
double x1, y1, x2, y2;
double area;
pair<double,double> center;
};
Map::Map(double a, double b, double c, double d)
{
x1 = a;
y1 = b;
x2 = c;
y2 = d;
area = (x1 - x2)*(y1 - y2);
double x, y;
x = (x1 + x2) / 2;
y = (y1 + y2) / 2;
center = make_pair(x, y);
}
map<string, map<double, vector<string>,greater<double>>> level;
map<string, Map> mapInfo;
bool isWithin(double x, double y, Map &m)
{
return x >= m.x2 && x <= m.x1 && y >= m.y2 && y <= m.y1;
}
double distance1(pair<double, double> &p1, pair<double, double> &p2)
{
return pow(abs(p1.first - p2.first), 2.0) + pow(abs(p1.second - p2.second), 2.0);
}
bool compare(string &s1, string &s2,pair<double,double> &p)
{
Map map1 = mapInfo[s1], map2 = mapInfo[s2];
double d1 = distance1(map1.center, p), d2 = distance1(map2.center, p);
if (d1 != d2)
return d1 < d2;
double ratio1 = (map1.y1 - map1.y2) / (map1.x1 - map1.x2);
double ratio2 = (map2.y1 - map2.y2) / (map2.x1 - map2.x2);
if (ratio1 != ratio2)
return abs(ratio1 - 0.75) < abs(ratio2 - 0.75);
pair<double, double> p1(map1.x1, map1.y2);
pair<double, double> p2(map2.x1, map2.y2);
double d3 = distance1(p1, p);
double d4 = distance1(p2, p);
if (d3 != d4)
return d1>d2;
return map1.x2 < map2.x2;
}
int main()
{
string line;
getline(cin, line);
while (getline(cin, line) && line != "LOCATIONS")
{
string name;
double x1, y1, x2, y2;
istringstream stream(line);
stream >> name >> x1 >> y1 >> x2 >> y2;
if (x1 < x2)
swap(x1, x2);
if (y1 < y2)
swap(y1, y2);
mapInfo[name] = Map(x1, y1, x2, y2);
}
while (getline(cin, line) && line != "REQUESTS")
{
istringstream stream(line);
string name;
double x, y;
stream >> name >> x >> y;
for (auto &m : mapInfo)
{
if (isWithin(x, y, m.second))
level[name][m.second.area].push_back(m.first);
}
for (auto &m : level[name]) //m是pair<double,vector<string>>
{
vector<string> temp(m.second);
pair<double, double> p(x, y);
sort(temp.begin(), temp.end(), bind(compare, placeholders::_1, placeholders::_2, p));
}
}
while (getline(cin, line) && line != "END")
{
istringstream stream(line);
string name;
int n;
stream >> name >> n;
if (!level.count(name))
{
cout << name << " at detail level " << n << " unknown location" << endl;
continue;
}
auto m = level[name];
if (level[name].empty())
cout << name << " " << "at" << " " << "detail level " << n << " no map contains that location" << endl;
else
{
int i = 1;
bool flag = false;
string temp;
for (auto it = m.begin(); it != m.end(); ++it,++i)
{
if (i == n)
{
cout << name << " at detail level " << n << " using " << it->second[0]<<endl;
flag = true;
}
if (i == m.size())
temp = it->second[0];
}
if (!flag)
cout << name << " at detail level " << n << " no map at that detail level; using " << temp << endl;
}
}
}