Xtreme10.0 - Food Truck

Xtreme10.0 - Food Truck
题目来源 第10届IEEE极限编程大赛
https://www.hackerrank.com/contests/ieeextreme-challenges/challenges/food-truck

Madhu has a food-truck called "The Yummy Goods" that goes to a different business hotspot every day at lunch! Madhu wants to perform location-based advertising to folks in the offices near her halt. To do this she uses the GPS location as a longitude and a latitude at the stop and decides on a radius (r) value. She wants to broadcast advertisement SMSes, to customers within this radius, advertising her food-truck.
She needs your help to generate the list of phone numbers of such folks. She has access to a big file of telecom data, which among other details, contains the phone number, longitude and latitude of active cell-phone users in the city at that moment.
In order to calculate the distance between her stops and her subscribers, she wants you to use the most recent location available for each subscriber. To calculate the distance, you should use the Haversine formula:
d = 2 × r × arcsin (sqrt (sin2((lat1 - lat2)/2) + cos(lat1) × cos(lat2) × sin2((long1 - long2)/2)))
where d is the distance between two points on the surface of the earth, in km's
r is the radius of the earth (6378.137 km for this problem)
lat1, long1 are the latitude and longitude, respectively, of point 1
lat2, long2 are the latitude and longitude, respectively, of point 2

Input Format

The first line contains Madhu's latitude and longitude in degrees, separated by a comma.
The second line contains the radius r in kms, within which she wants to broadcast her advertisement.
The third line is a header for the data in the subsequent lines.
The remaining lines have rows of telecom data of active cellphone users. Each line contains the following comma-separated fields:

  • A time stamp in MM/DD/YYYY hh:mm format. MM, is a two-digit month, e.g. 01 for January, DD is a two-digit day of month (01 through 31), YYYY is a four-digit year, hh is the two digits of hour (00 through 23), and mm is the two digits of minute (00 through 59)
  • The latitude of the subscriber, in degrees
  • The longitude of the subscriber, in degrees
  • The subscriber's phone number, as a 10-digit number

Notes:
Some subscribers may appear multiple times. You should use the most recent entry to determine the location and phone number of a subscriber. If a subscriber appears multiple times, the date/time stamps will differ.

None of the field values will contain commas.

Constraints

In order to eliminate rounding and approximation errors, no subscribers will be at a distance d from Madhu, such that 0.99 × rd ≤ 1.01 × r
1 ≤ r ≤ 100
There will be at most 50,000 lines in the subscriber list.

Output Format

A comma separated list of phone numbers for subscribers within a radius r of the stop, sorted in ascending order.

Sample Input

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

Sample Output

9020320007,9020320045,9020320084,9020357584,9020357593,9020357607

Explanation

We can calculate the distance between the location "18.9778972, 72.8321983" and each of the subscribers whose details are provided. Only the 6 phone numbers, listed in the Sample Output set, have a distance to the location of the food-truck that is less than 1.0 km.

题目解析
题目本身并没什么难的,但有几个地方容易犯错误。
几个注意事项:
首先Haversine公式里的经纬度是弧度、而输入的数据单位是角度,需要进行转换。
不要忘了所有的经纬度都要转换,包括店铺的位置和客户的位置。
读入数据用scanf比cin要容易一些。
可以创建一个结构体来保存用户的数据,key为电话号码。
输出的升序是电话号码的升序。
读取行数不确定的输入,可以用while(scanf(...) != EOF)
比较时间的前后关系,可以先把时间转换成一个数,转换过程中可以把每个月都算31天,每年都算366天。

程序
C++

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <map>
#include <string>

#define PI 3.1415926

using namespace std;

struct Custom {
    int year, month, day, hour, minute, second;
    double lat, long_;
    
    int timeNumber() const {
        return second + minute*60 + hour*3600 + day*86400 
               + month*2678400 + (year-1970)*980294400;
    }
    
    bool earlyThan(const Custom & that) {
        return timeNumber() < that.timeNumber();
    }
    
    bool inRange(double r, double myLat, double myLong) const {
        double d = 2 * 6378.137 * asin (sqrt ( pow(sin((lat-myLat)/2),2) + cos(lat) * cos(myLat) * pow(sin((long_-myLong)/2),2)));
        return d < r;
    }
};

double degree2radian(double degree) {
    return degree / 180 * PI;
}

int main() {
    double myLat, myLong, r;
    
    scanf("%lf,%lf", &myLat, &myLong);
    myLat = degree2radian(myLat);
    myLong = degree2radian(myLong);
    
    scanf("%lf", &r);
    map<long long, Custom> customs;

    string ignore;
    cin >> ignore;

    Custom c;
    long long phone;
    while(scanf("%d/%d/%d %d:%d,%lf,%lf,%lld", &c.day, &c.month, &c.year, &c.hour, &c.minute, &c.lat, &c.long_, &phone) != EOF) {
        c.lat = degree2radian(c.lat);
        c.long_ = degree2radian(c.long_);
        if(customs.find(phone) == customs.end()) {
            customs[phone] = c;
        }
        else {
            if(customs[phone].earlyThan(c)) {
                customs[phone] = c;
            }
        }
        c = customs[phone];
    }

    bool first = true;
    for(const auto kv : customs) {
        if( kv.second.inRange(r, myLat, myLong) ) {
            if(!first) cout << ',';
            first = false;
            cout << kv.first;
        }
    }

    return 0;
}

博客中的文章均为 meelo 原创,请务必以链接形式注明 本文地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容