1475 建设国家
小C现在想建设一个国家。这个国家中有一个首都,然后有若干个中间站,还有若干个城市。
现在小C想把国家建造成这样的形状:选若干(可以是0个)的中间站把他们连成一条直线,
然后把首都(首都也是一个中间站)连在这一条直线的左端。然后每个点可以连一个城市,特别的
是最右端的点可以连接两个城市。
现在有n个城市的规划供小C选择。但是,他们那儿的交通条件比较差,他们那儿一天是2*H个小时,
每个城市里面的人每天都会去首都拿一样东西,从他们所在的城市出发,到了首都之后拿了东西就走
(拿东西的时间可以忽略不计),他们要在2*H个小时之内返回他们自己的家中(从家中出发到返回
家中不超过2*H小时)。
每个城市有两个属性,一个是城市的直径,另外一个是能居住的人口数目。对于第i个城市而言,
这两个属性分别是hi,pi。
城市的直径的意思是离这个城市出口最远的人想要出城先要在城里行走的最少的时间。
在首都,中间站,城市之间行走要花费1小时的时间。
小C想选择一些城市然后通过若干的中间站和首都连接起来,在每个人能在2*H小时返回的条件下
所有城市居住的总人口数目要最多。
样例解释:最上面的蓝点表示首都,其它的蓝点表示中间站,剩下的红圈表示选择的城市。
收起
输入
单组测试数据。 第一行包含两个整数n 和H (1 ≤ n ≤ 1000,1 ≤ H ≤ 1000000000),表示可供选择的城市数 目和时间限制。 接下来n行,每行有两个整数hi, pi (1 ≤ hi ≤ H, 1 ≤ pi ≤ 1000),第i个城市的两个属性, 即直径和能容纳人口数。
输出
输出最多能居住的人口数目。
输入样例
5 10 1 1 1 1 2 2 3 3 4 4
输出样例
11
题意:
有N个城市,每个城市两个权值,time代表在城市中行走花费的时间,value代表该城市
有多少人,现在想通过一条链式的中间点将这些城市中的某一些关联起来,链头是首都,
且规定,每个中间节点只能连接一个城市,但是中间节点中的尾巴节点可以连接两个城市,
城市和中间点之间行走要花费一小时,现给定一时间H,要求最终构建的城市网络满足任意
一个城市中的人往返首都所花费的时间<=2*H,怎样构建这个网络能使得最终城市的人数
之和最大,求出最大人数和。
思路分析:
最大利润原题:
商店有N个商品,每个商品有一个到期时间和价值,且规定每天仅能出售一个商品,
问怎么安排出售商品的顺序能使得最终获得最大利润。
优先队列解法:
维护一个关于商品利润的小根堆, 对所有商品按照到期时间排序,顺序遍历所有商品。
若当前商品到期时间大于优先队列中商品数目,则该商品可以直接出售。
否则,即当前商品到期时间 t 等于优先队列中商品的数量,即前 t 天已经安排了 t 件
商品出售,则将其与堆中最小利润的物品比较,若其利润大,则用其去替换堆顶元素,
否则,继续遍历商品。
本题:
再看本题,如果用H-在城市中花费的时间,得到是从首都到不同城市所需要的
步数/时间。即从某时刻开始,在规定时间内必须到达某个城市,让我们从N个城市
中选择一些城市安排到规划中使得最终能获得最大利润。一样的题。
不同之处在于本题最后一天(相对的)可以出售两件物品。
解决方案:
即到达最后一个中间节点时特殊处理,但怎么判断当前的中间节点是否是尾节点并
不好判断,所以不妨对于每一个中间节点都当作最终的尾节点处理,在用其阶段中某个
利润较大城市替换之前城市之前,记录一下该城市连接到尾节点时的人口总和。因为随
着中间节点的增加,大利润城市不断对较小论润城市的替换,中间节点越多总利润越大。上述分析是错误的,即最大利润的方案并不一定在未变式的最终节点上添加点取得。
可能前几个所需时间少的城市具有很大的人口数,以至于通过增加中间节点增加的人口数
不如将某城市作为尾节点所连接城市最终贡献的人口数多。
综上当出现”到期时间“等于队列中城市数目的时候,假设当前就是在尾节点上添加第2城市,
即求出一个答案作为候选答案之一。
纠结问题:会不会最后添加的第二城市可以由前面被抛弃的某个城市替换从而得到
更大的价值。答案是不会,因为在替换之前已经把这种情况下的总价值求出来作为了
候选答案之一。
例如下图:
3步的8代替了2步的7,然后3步的6想最为最终第二城市,但显然
和
的组成更优,
但这种情况在
替换
之前已经被试过并保存了临时答案。
代码实现:
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int N=2e5+100;
struct Node{
int time,value;
}arr[N];
bool cmp(Node aa,Node bb){
return aa.time<bb.time;
}
priority_queue<int ,vector<int>,greater<int> >Q;
int main() {
int n,h,ans,maxs;
while(cin>>n>>h){
while(Q.size())Q.pop();
ans=maxs=0;
for(int i=1;i<=n;i++){
cin>>arr[i].time>>arr[i].value;
arr[i].time=h-arr[i].time;
}
sort(arr+1,arr+1+n,cmp);
for(int i=1;i<=n;i++){
if(arr[i].time<=0)continue;
if(arr[i].time>Q.size()){
Q.push(arr[i].value);
ans+=arr[i].value;
}else {
maxs=max(maxs,ans+arr[i].value);//作为候选答案
if(arr[i].value>Q.top()){
ans-=Q.top();
Q.pop();
Q.push(arr[i].value);
ans+=arr[i].value;
}
}
}
ans=max(ans,maxs);
cout<<ans<<endl;
}
return 0;
}
THE END;