51nod 1475:建设国家 优先队列的好题

基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题
 收藏
 关注

小C现在想建设一个国家。这个国家中有一个首都,然后有若干个中间站,还有若干个城市。

现在小C想把国家建造成这样的形状:选若干(可以是0个)的中间站把他们连成一条直线,然后把首都连在这一条直线的左端。然后每个点可以连一个城市,特别的是最右端的点可以连接两个城市。

现在有n个城市的规划供小C选择。但是,他们那儿的交通条件比较差,他们那儿一天是2*H个小时,每个城市里面的人每天都会去首都拿一样东西,从他们所在的城市出发,到了首都之后拿了东西就走(拿东西的时间可以忽略不计),他们要在2*H个小时之内返回他们自己的家中(从家中出发到返回家中不超过2*H小时)。

每个城市有两个属性,一个是城市的直径,另外一个是能居住的人口数目。对于第i个城市而言,这两个属性分别是hi,pi。

城市的直径的意思是离这个城市出口最远的人想要出城先要在城里行走的最少的时间。

在首都,中间站,城市之间行走要花费1小时的时间。

小C想选择一些城市然后通过若干的中间站和首都连接起来,在每个人能在2*H小时返回的条件下所有城市居住的总人口数目要最多。

样例解释:最上面的蓝点表示首都,其它的蓝点表示中间站,剩下的红圈表示选择的城市。

Input
单组测试数据。
第一行包含两个整数n 和H (1 ≤ n ≤ 1000,1 ≤ H ≤ 1000000000),表示可供选择的城市数目和时间限制。
接下来n行,每行有两个整数hi, pi (1 ≤ hi ≤ H, 1 ≤ pi ≤ 1000),第i个城市的两个属性,即直径和能容纳人口数。
Output
输出最多能居住的人口数目。
Input示例
5 10
1 1
1 1
2 2
3 3
4 4
Output示例
11

我到现在还在想为什么这道题仅仅是20分的一道题,一开始做的时候题意都没能完全理解。。。理解了之后发现情况怎么这么多,要考虑的因素怎么这么多,用优先队列是肯定的,怎么用都是个问题。。。最后是一位大神把代码发过来,跑了几次之后,才理解。但现在,对这道题真的是快要膜拜了,无论是出题人还是写出这种做法的人,可能是我水平现在太弱了,这个代码仔细想了想,写得是真的6。膜拜~

将距离按照降序排列,然后在只有满足当前数量<i的时候往里面添加元素,弹出来的是当前队列中的人口最少的城市,队列中的是被选中的满足接下来长度要求的城市,然后在这一轮中添加这个距离的所有城市,之后如果城市数量超出,再将人口最少的城市排除。也就是说,队列里面是符合长度要求的人口最多且在当前状况下数量最多的城市。

膜拜大神~

代码:

#include <iostream>
#include <vector>
#include <queue>
#pragma warning(disable:4996)
using namespace std;

const int N = 1005;
int n,H;
vector <int> v[N];

int main()
{	
	scanf("%d%d",&n,&H);
	for(int h,p,i=0;i<n;i++)
	{
		scanf("%d%d",&h,&p);
		int x = min(n,H-h);
		v[x].push_back(p);
	}
	priority_queue<int>q;
	int ans = 0;
	for(int i=1,s=0;i<=n;i++)
	{
		for(;q.size()>=i;q.pop())
			s+=q.top();
		for(auto &p:v[i])
		{
			q.push(-p);
			s += p;
		}
		for(;q.size()>i+1;q.pop())
		{
			s += q.top();
		}
		ans = max(ans,s);
	}
	printf("%d\n",ans);
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

posted on 2015-09-28 16:12  光速小子  阅读(276)  评论(0编辑  收藏  举报

导航