习题:Kisik(贪心)

题目:

银河国家殖民地联盟(CAIN)决定在火星上为K个家庭建造一座城市,因此,必须要为每个家庭建造一座房子,即一共K座房子。对于每个家庭,将可以选择从银河系最好的建筑师准备的N种建筑中选择一种。对于所有的建筑物,都是矩形,第i种建筑宽Wi,高Hi。此外,由于CAIN推广各种品种,所有的家庭将获得不同的设计。

各个建筑彼此相邻建造,因此,他们的底部位于同一条线上。建成后,因为城市需要充满空气,因此这个城市将被一个巨大的玻璃墙包围,将空气保持在里面。玻璃墙也是矩形形状,其侧面平行于建筑物侧面。

由于保持火星上的空气价格十分昂贵,因此您的工作就是在所有可能中选择空气最少(即玻璃墙包围面积最小)的方案。

输入格式

第一行输入2个数字N,K(1≤K≤N≤1000000),表示房屋类型的种类和总共的户数。

接下来N行,每行输入两个数字Wi,Hi(1≤Wi,Hi≤1000000),用空格隔开,表示第i种房屋类型的宽和高。

输出格式

输出一个数字,表示最少需要的空气量。

样例

样例输入1

4 3
2 3
2 2
1 4
3 2

样例输出1

20

样例输入2

3 3
1 1
3 3
2 2

样例输出2

18

样例输入3

4 1
6 4
4 5
19 1
3 6

样例输出3

18

思路:
考虑到每一个矩阵的计算,宽一定是选的所有房子的最大值,长一定是选的是所有矩阵的宽的和,那么我们自然而然地就可以讲到贪心策略,对于每一个高,我们只需将宽最小即可,考虑

将宽保证最小即可,那么维护这个最小值自然而然就想到可以用优先队列来维护。

代码:

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
long long n,k;
long long s;
long long ans=1ll*1000000*1000000*1000000+5;
pair<long long,long long> b[1000005];
priority_queue<long long> q;
int main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	{
		cin>>b[i].fi>>b[i].se;
		swap(b[i].fi,b[i].se);
	}
	sort(b+1,b+n+1);
	for(int i=1;i<=k;i++)
	{
		s+=b[i].se;
		q.push(b[i].se);
	}
	for(int i=k;i<=n;i++)
	{
		ans=min(ans,s*b[i].fi);
		//cout<<ans<<endl;
		s+=b[i+1].se;
		q.push(b[i+1].se);
		s-=q.top();
		q.pop();
	}
	cout<<ans;
	return 0;
}

 

posted @ 2019-08-23 19:29  loney_s  阅读(134)  评论(0)    收藏  举报