51nod 1475 建设国家 优先队列

来源:互联网 发布:办公软件英文怎么说 编辑:程序博客网 时间:2024/06/05 12:06

小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 101 11 12 23 34 4
Output示例
11
System Message (题目提供者)
还是一道优先队列的题目。
对于n个城市,我们先求出每个城市最大,之后倒着来放。先放承受能力大的。
之后对于第i层,如果队列数量大于等于i了,先取出小的,变成i-1。
之后开始把这一层能承受的城市全都放入队列。
放完后可能对多了,我们要在取出一些小的,让队列数量变成i+1,之所以是i+1不是i,是因为最后一个位置能放两个。
其实就是贪心处理每一层,让每一层都是最优解,之后求出最大的即可。


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
const int N=1005;
using namespace std;
priority_queue<long long ,vector<long long >,greater<long long> >pq;
vector<int>v[N];
int main()
{
    int n,H,x,p,q,t;
    cin>>n>>H;
    for(int i=1;i<=n;i++)
    {
        cin>>p>>q;
        t=min(n,H-p);  //总长度为H,该城市直径为p,也就是说这个城市最大只能放在H-p的位置,或者以上。不能再远了。当前这个位置
//为t的城市,也可以放在t-1,t-2等位置。
        v[t].push_back(q);
    }
    int ans=0;
    int sum=0;
    for(int i=1;i<=n;i++)  //枚举每一个位置
    {
        for(;pq.size()>=i;pq.pop())  //假设倒了第i个位置了,我们一般里面放着i+1个城市,因为局部最优解的原因,最后一个位置能放两个嘛,现在我们又加了一层,这一层就只能放一个了。所以先把最小的拿出来
        {
            sum=sum-pq.top();
        }
        for(int j=0;j<v[i].size();j++)
        {
            sum+=v[i][j];
            pq.push(v[i][j]);//所有可以放到这一层的城市全部放进入
        }
        for(;pq.size()>i+1;pq.pop())  //全都放进入之后再把最小的全都踢出去
        {                                  //注意这里是大于i+1,因为我们最后一个位置可以放两个的..也就是可以多放一个。
            sum=sum-pq.top();
        }
        ans=max(ans,sum);
    }
    cout<<ans<<endl;
}
原创粉丝点击