Xtreme10.0 - Food Truck

Xtreme 10.0 - Food Truck


题目:

https://www.hackerrank.com/contests/ieeextreme-challenges/challenges/food-truck


题意:

        Madhu是一个食品商,为了增加生意收入,他决定向附近的客户派发广告。给定Madhu所处位置的经纬度、派发广告的半径范围、以及周围客户的通讯信息(客户通讯信息包括:时间戳、经纬度以及电话号码)。替Madhu写一个程序,帮助Madhu挑选出与与其相对位置的距离小于所设半径范围的所有客户的电话号码。

        注意:

        1、其中同一个客户可能在不同时间段出现在不同的地点,此时以该客户的最新时间为位置为基准。

        2、距离的计算公式为:d = 2 × r × arcsin (sqrt (sin2((lat1 - lat2)/2) + cos(lat1) × cos(lat2) × sin2((long1 - long2)/2)))。其中d表示两点间的距离,单位是千米;r表示地球的半径,取值为6378.137千米;lat1,long1表示第一个点的经纬度;lat2,long2表示第二个点的经纬度。


输入:

        第一行的两个数表示Madhu位置的经纬度,用逗号隔开。

        第二行为所设定派送广告的半径范围,单位为千米,范围为[1, 100]。

        第三行为客户通讯信息的标题部分。

        接下来的n行是客户通讯信息,包括时间戳(格式为MM/DD/YYYY hh:mm)、经纬度(角度值)、客户电话号码(10个数字)。通讯信息最多不超过1000行。


输出:
        与Madhu相距距离小于所设半径范围的所有客户的电话信息,以升序排列,用逗号分隔开。

测试用例:

输入:

18.9778972,72.8321983
1.0
Date&Time,Latitude,Longitude,PhoneNumber
10/21/2016 13:34,18.912875,72.822318,9020320100
10/21/2016 10:35,18.9582233,72.8275845,9020320024
10/21/2016 15:20,18.95169982,72.83525604,9020320047
10/21/2016 15:23,18.9513048,72.8343388,9020357980
10/21/2016 15:23,18.9513048,72.8343388,9020357962
10/21/2016 15:28,18.9548652,72.8332443,9020320027
10/21/2016 14:03,18.9179784,72.8279306,9020357972
10/21/2016 14:03,18.9179784,72.8279306,9020357959
10/21/2016 09:52,18.97523123,72.83494895,9020320007
10/21/2016 09:44,18.9715932,72.8383992,9020357607
10/21/2016 09:44,18.9715932,72.8383992,9020357593
10/21/2016 09:44,18.9715932,72.8383992,9020357584
10/21/2016 14:57,18.93438826,72.82704499,9020320011
10/21/2016 09:56,18.97596514,72.8327072,9020320045
10/21/2016 08:33,18.9811929,72.8353202,9020320084
10/21/2016 13:27,18.9159265,72.8245989,9020357896
10/21/2016 13:09,18.9077347,72.8076201,9020320094
10/21/2016 10:52,18.97523003,72.83494865,9020320007


输出:

9020320007,9020320045,9020320084,9020357584,9020357593,9020357607


思路:

        按题目要求做就行了。其中要注意:1、计算距离时要注意将角度转化为弧度。2、同一个客户可能在不同时间段出现在不同位置,因此要取最新出现一条信息进行判断。3、结果注意要排序输出。

代码:

#include <cmath>
#include <string>
#include <cstdio>
#include <vector>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;

#define M_PI 3.1415926535898

class Item {
public:
	double latitude;
	double longitude;
	long long PhoneNumber;
	time_t time;
	string timeStr;
	Item(string s) {
		unsigned int sp = s.find_first_of(',');
		string tStr(s.begin(), s.begin() + sp);
		timeStr = tStr;
		time = getTimeByStr(tStr);

		string tmp(s.begin() + sp + 1, s.end());

		int sp1 = tmp.find_first_of(',');
		int sp2 = tmp.find_last_of(',');
		string s1(tmp.begin(), tmp.begin() + sp1);
		string s2(tmp.begin() + sp1 + 1, tmp.begin() + sp2);
		string s3(tmp.begin() + sp2 + 1, tmp.end());

		latitude = stod(s1);
		longitude = stod(s2);
		PhoneNumber = stoll(s3);
	}
private:
	time_t getTimeByStr(string s) {
		tm time;
		//10/21/2016 13:34
		sscanf(s.c_str(), "%d/%d/%d %d:%d",
			&time.tm_mon, &time.tm_mday, &time.tm_year,
			&time.tm_hour, &time.tm_min);
		time.tm_year -= 1900;
		time.tm_mon -= 1;
		time.tm_sec = 0;

		time_t res = mktime(&time);
		return res;
	}


};

double distanceBetween(double lat1, double longt1, double lat2, double longt2) {
	lat1 = lat1 * M_PI / 180;
	lat2 = lat2 * M_PI / 180;
	longt1 = longt1 * M_PI / 180;
	longt2 = longt2 * M_PI / 180;

	double tmp1 = pow(sin((lat1 - lat2) / 2 ), 2);
	double tmp2 = pow(sin((longt1 - longt2) / 2), 2);
	double tmp3 = tmp1 + cos(lat1) * cos(lat2) * tmp2;
	double tmp4 = sqrt(tmp3);
	double r = 6378.137;
	return 2 * r * asin(tmp4);
}

bool lessThan(const Item &item1, const Item &item2) {
	if (item1.PhoneNumber < item2.PhoneNumber) return true;
	else if (item1.PhoneNumber > item2.PhoneNumber) return false;
	else if (item1.PhoneNumber == item2.PhoneNumber) {
		if (item1.time > item2.time) return true;
		else return false;
	}
	return false;
}

void upDateMap(unordered_map<long long, Item> &items, const Item &item) {
	unordered_map<long long, Item>::iterator got = items.find(item.PhoneNumber);
	if (got != items.end() && got->second.time < item.time) {
		items.erase(got);
	}
	items.insert(pair<long long, Item>(item.PhoneNumber, item));
	return;
}

void foodTruck() {
	double lat = 0.0, lon = 0.0;
	//cin >> lat >> lon;
	scanf("%lf,%lf", &lat, &lon);
	double aimDist = 0.0;
	cin >> aimDist;

	string inStr;
	getchar();
	getline(cin, inStr);

	unordered_map<long long, Item> items;
	while (1) {
		getline(cin, inStr);
		if (cin.eof()) break;
		Item item(inStr);
		upDateMap(items, item);
	}

	vector<Item> res;
	for (unordered_map<long long, Item>::iterator it = items.begin();
		it != items.end(); it++) {
		Item item = it->second;
		double distance = distanceBetween(lat, lon, item.latitude, item.longitude);
		if (distance < aimDist) {
			res.push_back(item);
		}
	}
	sort(res.begin(), res.end(), lessThan);
	for (vector<Item>::iterator it = res.begin(); it != res.end(); it++) {
		if (it != res.begin() && (*it).PhoneNumber == (*(it - 1)).PhoneNumber) continue;
		if (it != res.end() - 1) cout << (*it).PhoneNumber << ',';
		else cout << (*it).PhoneNumber << endl;
	}
}

int main() {
	foodTruck();
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值