您的位置:首页 > 其它

[原创]百度之星2009初赛第二场第四题解答

2009-05-31 22:02 295 查看

[b]百度之星2009程序设计大赛 初赛第二场[/b]第四题解答

题目:

4. 我的地盘 (350分)

题目描述

百度公司的员工们在工作之余,经常以产品组为单位组织一些活动,包括吃大餐、春游秋游、公益活动、唱KTV、看电影、体育比赛等。这些活动有一个专业的名字,叫做team building,我们也亲切的称之为“bui”。

0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" class="aligncenter size-full wp-image-14024" title="bui" src="http://www.baiduer.com.cn/wp-content/uploads/2009/05/bui.jpg" alt="bui" width="282" height="176">

最近,地图产品组刚刚完成一个大项目,大家决定大bui一场。一阵七嘴八舌后,很多内容被提了出来,最终确定先打乒乓球,然后吃饭,最后K歌。问题是,谁也不知道有什么地方可以同时满足这三个需求。

不过没有什么问题可以难倒我们的工程师。很快,就有人写出了程序,为大家找到了合适的地点。

地图覆盖之处,皆为我的地盘。你想挑战一下我们的工程师吗?想为我们找出更合适的地点吗?那就来吧。

输入格式

第1行是一个整数k,表示某范围内所有的POI(Point of Interest)点数量,后续k行每行用5个字段描述一个POI点。它们的含义和格式如下表:

内容 数据格式 数据范围

POI编号 Int,唯一 [0,231-1]

POI类型 字符串 0-16字节(不超过15种类型)

POI级别 Int 0-5(越大表示越高级)

POI经度 Double [0,180],6位有效精度

POI纬度 Double [0,180],6位有效精度

需要注意的是这里的经纬度跟通常的经纬度范围是不一样的

随后是一个整数n(0 < n <= 20),表示共n组查询。以下n行,每行表示一组查询,格式为:

POI类型1 POI类型2 POI类型3 最低级别 最高级别

分别表示三个bui地点各自的类型、最低级别和最高级别。

输出格式

对于每组查询”t1 t2 t3 min max”,输出三个POI编号p1、p2、p3,满足:

•p1、p2、p3的类型分别为t1、t2和t3。

•p1、p2、p3的级别不小于min,不大于max。

•p1、p2、p3的两两欧几里得距离之和应尽量小。

输入数据保证至少存在一个解。

样例输入

5

1 休闲娱乐 3 11.122843 12.431021

2 餐饮服务 2 13.384021 10.230425

3 旅游景点 3 12.234492 9.234268

4 休闲娱乐 5 20.242391 39.304233

5 教育机构 1 42.243292 67.232065

1

休闲娱乐 餐饮服务 旅游景点 0 5

样例输出

1 2 3

测试数据

点击此处下载一份POI数据。所有测试点中的POI数据都基于此数据生成。可能的变动包括:

•修改POI编号

•对经纬度加入随机干扰(变化不会超过1%)。

•修改POI类别和级别

•加入不超过1%的新点,各项属性均完全随机

共20组测试点,其中第i个测试点包含i组查询。1 <= i <= 20

注意事项

•对于每个测试点,设已知最优解为D,则不超过1.05D的任意解均是可以接受的。

•请不要把离线计算的结果保存在源代码中(例如,直接把某些输入的答案保存在常量数组中,读取输入后直接输出),否则本题得0分。

分析:由于不需要求最优解,因此不用全部遍历,使用贪心法寻找离 当前已选择点集合 最近的点,不过没有测试是否最优,比赛的时候提交的是没有优化的代码,比完后又花了半个钟才完成了以下代码,感觉编码速度还是有待加强。

我的水平只能弄出这样的结果了,不过应该还有更优的解法。

#include <stdio.h>

#include <string>

#include <math.h>

#include <stdlib.h>

#include <iostream>

#include <vector>

#include <algorithm>

using namespace std;

struct POI

{

int id;

string kind;

int level;

double x;

double y;

};

int main()

{

int k,n,i,j;

vector<POI> all;

scanf("%d",&k);

for(i=0;i<k;i++)

{

POI temp;

cin>>temp.id>>temp.kind>>temp.level>>temp.x>>temp.y;

all.push_back(temp);

}

scanf("%d",&n);

for(i=0;i<n;i++)

{

string t[3];

int min,max;

cin>>t[0]>>t[1]>>t[2]>>min>>max;

int index[3]={0},totalindex[3]={0};

index[0]=-1;

double totalmindis = 360*360*3;

//方法:第一个POI选择所有可能的值,然后对每个可能的第一个POI,选择离他最近的第二个POI,

//选好第二个后,选择离前面两个距离之和最小的那个为第三个POI,

//选好三个后计算总距离,如果小于前一个解则更新解,终结条件是找到所有可能的第一个POI

while(index[0]<(int)all.size())

{

double curtotal = 0;

for(j=0;j<3;j++)

{

double mindis1 = 360*360;

double mindis2 = 360*360*2;

for(k=0;k<all.size();k++)

{

if(t[j]==all[k].kind&&all[k].level>=min&&all[k].level<=max)

{

//第一个POI

if(j==0)

{

if(k>index[0])

{

index[j] = k;

break;

}

}

//第二个POI

else if(j==1)

{

double dis = (all[k].x-all[index[j-1]].x)*(all[k].x-all[index[j-1]].x)+

(all[k].y-all[index[j-1]].y)*(all[k].y-all[index[j-1]].y);

if(dis<mindis1)

{

index[j]=k;

mindis1 = dis;

}

}

//第三个POI

else if(j==2)

{

double dis=0;

int t;

for(t=0;t<j;t++)

{

dis += (all[k].x-all[index[t]].x)*(all[k].x-all[index[t]].x)+

(all[k].y-all[index[t]].y)*(all[k].y-all[index[t]].y);

}

if(dis<mindis2)

{

index[j]=k;

mindis2 = dis;

}

}

}

}

//计算当前的总距离

if(j==1)

curtotal += mindis1;

if(j==2)

curtotal += mindis2;

//判断是否已经试过第一个POI的所有可能

if(j==0&&k==all.size())

index[j]=k;

}

if(curtotal<totalmindis&&index[0]!=all.size())

{

totalindex[0] = index[0];

totalindex[1] = index[1];

totalindex[2] = index[2];

totalmindis = curtotal;

}

}

cout<<all[totalindex[0]].id<<"
"<<all[totalindex[1]].id<<"
"<<all[totalindex[2]].id<<endl;

}

return 0;

}

弄了一组测试数据:

15

1 休闲娱乐 5 20.242391 39.304233

2 餐饮服务 2 13.384021 10.230425

3 旅游景点 3 12.234492 9.234268

4 休闲娱乐 3 11.122843 12.431021

5 教育机构 1 42.243292 67.232065

6 餐饮服务 2 113.054282 29.098546357

7 旅游景点 5 116.834988 39.952290455

8 旅游景点 5 113.166512 22.922672903

9 餐饮服务 2 113.054439 29.0987291154

10 文化教育 3 113.282175 23.201096485

11 综合商场 5 113.166579 22.923254613

12 金融行业 1 117.219020 36.500982133

13 文化教育 5 113.755876 39.739886517

14 综合商场 3 114.120915 36.1436581215

15 金融行业 5 104.688191 30.1736361401

5

休闲娱乐 餐饮服务 旅游景点 0 5

餐饮服务 休闲娱乐 旅游景点 0 5

金融行业 文化教育 综合商场 0 5

旅游景点 餐饮服务 金融行业 0 5

文化教育 餐饮服务 金融行业 0 5

我的答案是:

4 2 3

2 4 3

12 13 14

7 9 12

13 9 12
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: