Time Limit: 1 second
Memory Limit: 128 MB
【问题描述】
这场灾难发生后,国家决定设立研究所研究灾后重建工作,由全国各地派技术人员来参加。因为每个地区所派的技术人员数目不
同,出于节约经费的问题,所以目前还没有决定到底有在哪个地区设置研究所进行研究。假设所有地区都在一条直线上,现在
只知道每个地区与汶川的距离和该地派出技术人员的数目(假设汶川在最左端)。请你编程帮助他们确定在哪个地区建立研究
所可以使所有技术人员集中到该地区的费用总和最小。
【输入格式】
输入文件每一行描述一个地区的信息(地区数<=5000)。 对于每一行,首先是该地区派出的技术人员数目,紧跟着是这个地区相对于汶川的距离,最后是该地区的名称。(技术人员数<=100,地区的相对距离<=10^31,地区名称长度<=20,数据保证有唯一的解);
【输出格式】
输出文件只需一行,即研究所设定的地区名称。
【数据规模】
Sample Input1
7 9289 shengyan
5 8523 beijing
3 5184 guilin
8 2213 chongqing
10 0 wuhan
Sample Output1
chongqing
【题目链接】:http://noi.qz5z.com/viewtask.asp?id=u231
【题解】
这类一个横轴上有多个低点;
每个点除了坐标之外还有一个权值;
然后让求使得∑w[i]*|x[i]-x[k]|最小的k
带权中位数问题;
本来如果权值为1;
(每个点都只有一个人)
->∑|x[i]-x[k]|;
现在权值不为1;
做法是累加前i个点的人数
即
∑(num[i])
找到第一个i
满足
∑(num[i])>=tot/2;
这里tot为num[1]+num[2]+..+num[n];
(其实这个东西对权值为1的也适用.把num都换成1就是了;)
然后所求的i就是最优解;
【完整代码】
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = 5e3+100;
struct abc
{
int num;
double dis;
string name;
friend bool operator < (abc a,abc b)
{
if (a.dis==b.dis)
return true;
else
return a.dis < b.dis;
}
};
abc a[MAXN];
int n = 1,tot = 0;
int main()
{
//freopen("F:\rush.txt","r",stdin);
while (cin >> a[n].num >> a[n].dis >> a[n].name) tot+=a[n].num,n++;
n--;
sort(a+1,a+1+n);
int sum = 0;
for (int i = 1;i <= n;i++)
{
sum+=a[i].num;
if (sum >= tot/2)
{
cout << a[i].name<<endl;
return 0;
}
}
return 0;
}