zoukankan      html  css  js  c++  java
  • UVA

    /*
      法一借鉴自:
      http://blog.csdn.net/zay999abc/article/details/49836073
      
      
      收获:
      1. C++11中的default关键字
      最简单易懂的解释:
      如果自定义了构造函数,那么默认构造函数就不可以用了,强制=default声明可以让默认构造函数恢复。
      
      有关资料:
      http://www.cnblogs.com/zhuyijie/p/6464590.html
      http://blog.csdn.net/a1875566250/article/details/40406883
      http://bbs.csdn.net/topics/390689526
      
      
      2. STL 中的map,可对键值按降序排序
      http://www.cnblogs.com/youngforever/articles/3314501.html
      
      3. C++11 中的关键字 bind 和 placeholder 及其有关用法
      http://www.cplusplus.com/reference/functional/bind/?kw=bind
      http://www.cplusplus.com/reference/functional/placeholders/
      http://blog.csdn.net/wangshubo1989/article/details/50471709
      http://blog.csdn.net/segen_jaa/article/details/51155218
       
    */

    #include <iostream>
    #include <map>
    #include <string>
    #include <cmath>
    #include <vector>
    #include <sstream>
    #include <algorithm>
    #include <functional> //bind 和 placeholders 
    using namespace std;
    typedef pair<double, double> p_double;
    const double EPS = 1e-7;
    
    bool is_dif (const double&a, const double& b) // if is different,实际作用:代替double的不等号
    {
    	return !( fabs(a - b) < EPS);
    } 
    
    struct Map
    {
    	double x1, y1, x2, y2, area, length, width;
    	p_double center;
    	
    	Map() = default; 
    	Map(double a, double b, double c, double d):x1(a), y1(b), x2(c), y2(d)
    	{
    		length = max(x1 - x2, y1 - y2); width = min(x1 - x2, y1 - y2);
    		area = length * width;
    		double x = (x1 + x2) / 2.0, y = (y1 + y2) / 2.0;
    		center = make_pair(x, y);
    	} //在传参数到构造函数前,已经经过了可能需要的交换,以保证 x1 >= x2 && y1 >= y2
    };
    
    map<string, map<double, vector<string>, greater<double> > > level; //前一个string表示地点名,double表示的是地图面积(由面积可得其详细等级),之所以map要降序排序,是因为面积越小越详细,详细等级越高,vecto<string>表示的是对于某一地点,有多少详细等级在double的地图,保存其地图名到vector中 
    map<string, Map> mapInfo; //保存地图名和地图的对应关系 
    
    bool isWithin(double x, double y, const Map &m)
    {
    	return x >= m.x2 && x <= m.x1 && y >= m.y2 && y <= m.y1;
    }
    double distance1 (p_double &p1, p_double &p2)
    {
    	return pow(p1.first - p2.first, 2) + pow(p1.second - p2.second, 2);
    }
    bool mycmp(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 (is_dif(d1, d2)) return d1 < d2;
    	
    	double ratio1 =  map1.length / map1.width, ratio2 = map2.length / map2.width;
    	double gap1 = fabs(ratio1 - 0.75), gap2 = fabs(ratio2 - 0.75);
    	if (is_dif(gap1, gap2)) return gap1 < gap2;
    	
    	pair<double, double> p1(map1.x1, map1.y2); //地图1的右下角坐标
    	pair<double, double> p2(map2.x1, map2.y2); //地图2的右下角坐标
    	double d3 = distance1(p, p1), d4 = distance1(p, p2);
    	if (is_dif(d3, d4)) return d3 > d4;
    	
    	return  map1.x2 < map2.x2; //对于所有地图,构造时已确保x1>=x2,找最小,自然该从x2找 
    }
    
    int main()
    {
    	string s;
    	getline(cin, s);
    	while (getline(cin, s) && s != "LOCATIONS")
    	{
    		string name;
    		double x1, y1, x2, y2; //分离出地图名和其对角线坐标
    		
    		istringstream ss(s);
    		ss >> name >> x1 >> y1 >> x2 >>  y2;
    		if (x1 < x2) swap(x1, x2);
    		if (y1 < y2) swap(y1, y2); //构造地图前,先确保 x1 >= x2 && y1 >= y2 
    		mapInfo[name] = Map(x1, y1, x2, y2);
    	}
    	
    	while(getline(cin, s) && s != "REQUESTS")
    	{
    		istringstream ss (s);
    		string name;
    		double x, y;
    		ss >> name >> x >> y;
    		
    		for (auto &m : mapInfo) //auto是C++11新特性,此处语义为:遍历 mapInfo 中的所有 key_value对,m.first表示的就是 key(string类),m.second表示的是value(Map对象) 
    		{ //m是 pair(string, Map) 
    			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(mycmp, placeholders::_1, placeholders::_2, p) );
    		}
    	}
    	
    	while (getline(cin, s) && s != "END")
    	{
    		istringstream ss (s);
    		string name;
    		int n;
    		ss >> name >> n;
    		
    		if (!level.count(name)) //没有该地的地名 
    		{
    			cout << name << " at detail level " << n << " unknown location" << endl;
    			continue;
    		}
    		
    		auto &m = level[name];
    		if (m.empty()) //没有地图 
    		{
    			cout << name << " at detail level " << n << " no map contains that location" << endl;
    			continue;
    		}
    		
    		int i = 1; bool flag = false; string tp; //temp
    		for (auto it = m.begin(); it != m.end(); it++, i++)
    		{
    			if (i == n) //找到详细等级为n的地图 
    			{
    				cout << name << " at detail level " << n << " using " << it->second[0] << endl;
    				flag = true;
    				break;
    			}
    			if (i == m.size()) tp = it->second[0]; //没找到详细等级为n时,要输出的是最详细的地图
    		}
    		if (!flag) cout << name << " at detail level " << n << " no map at that detail level; using " << tp << endl;
    	}
    	return 0;
    }



    /*
      法二:
      后来又看了一个博主的博客
      http://blog.csdn.net/kun768/article/details/43966329
      
      
      总结他的代码,给我的收获如下
      1. hypot函数(可根据直角边求得斜边)
      http://www.cplusplus.com/reference/cmath/hypot/
      
      2. 浮点数的相等不等比较,不能用简单地 != 和 == ,一定要用到一个足够小的EPS(一般为1e-7)
      
      这个真是特别汗颜,直到看到这个博主的代码,我才想起来,之前还因为这个WA过,这次侥幸AC,赶紧回去改了下自己的代码...(于是我的代码才有了EPS,本来我忘记这个坑点了,用 != 去比较了...)
      
      3. find_if的写法
      
      这个博主在find_if里面写的...其实我一直都没有看懂,他的原代码是:
    
      
    */
      for (auto & i : C1)
    				i.ilevel = find_if(all_area.begin(), all_area.end(), [i](const double area)
    				{return fabs(area - i.area) <= EPS; }) - all_area.begin() + 1;

    /*
      然而我几乎查遍了所有find_if的用法,也还是不明白,他为什么可以直接把函数写到find_if的第三个参数
      
      而且这第三个函数也有些看不懂,我曾经试图把它改到外面,做为一个函数,然后find_if的第三个参数只传入函数名进去,但我改了好几次失败了...然而原博主的这种写法,却又一直看不懂
      
      于是最后,我只能把 find_if那段,换成了用find来写,这次很高兴地发现,改对了
    */
    for (auto & i : C1)
    			i.ilevel = find(all_area.begin(), all_area.end(), i.area) - all_area.begin() + 1;
    		
    /*
      另附有关find_if函数的一些网站(确实找遍了所有的网站,都没有看到博主这样高端的写法,可能我目前段位太低,此处留坑,希望以后看到,还有机会弄明白)
      http://www.cplusplus.com/reference/algorithm/find_if/
      http://blog.csdn.net/wangshubo1989/article/details/50389811
      http://www.cnblogs.com/cy568searchx/archive/2013/08/28/3286684.html
      
      -------接着写收获的分割线-------
      
      4. copy_if 和 back_inserter
      同样地,我也是只能弄懂语法,但看不太懂博主的代码,此处先留坑,日后有机会再弄懂,我觉得这个博主的这两句代码(find_if那句, copy_if那句),似乎超出了我目前的知识水平,日后再来细看
      
    */


    /*
      同时我还看了法三,虽然没有自己敲一次这个方法
      法三来自blog:
      http://blog.csdn.net/wangjinhaowjh/article/details/50563296
      法三和法二本质相同,除了用循环代替了我在法二中看不懂写法的find_if和copy_if
      
      虽然,之前查资料时,又看到这段话
      
      假如vector用vector查找复合类型的对象,这个时候一般的想法是写个函数遍历这个vector,然后进行比较查找。实际上在使用STL的时候,不建议使用循环遍历的查找方法,有几个理由
      (参见《effictive c++》46条):
      效率:泛型算法通常比循环高效。 
      正确性: 写循环时比调用泛型算法更容易产生错误。 
      可维护性: 与相应的显式循环相比,泛型算法通常使代码更干净、更直观。
      
      但是,奈何我现在,真的不太理解法二的泛型算法,实在看不懂,所以,不能走最优解的话,只少应该知道有什么替代的方法,法三就是可以替代的方法
      
      另外,其实unique不是真正的去重,只是将重复的移到末端,要真正去重,还要和 erase一起使用,但就这题而言,按照博主的循环的写法,不用erase不影响AC,但是万一下次的出题方式,导致会影响了呢?
      
      所以不如将
      unique(area.begin(),area.end()); 
      改为:
      area.erase(unique(area.begin(),area.end()), area.end());	
      
    */


  • 相关阅读:
    XNA入门教程(一)
    SQL透视表
    java 远程ftp建立文件夹
    费事数列——我的理解
    OOP
    OOP2
    河内之塔
    获取页面上TextBox并改变它的值
    RMAN学习之三:归档模式有备份,丢失控制文件。
    SQL Server Error: [DBNETLIB][ConnectionOpen (Connect()).]SQL Server 不存在或访问
  • 原文地址:https://www.cnblogs.com/mofushaohua/p/7789413.html
Copyright © 2011-2022 走看看