[USACO 2007 Jan S]Protecting the Flower(贪心)

传送门

题意:要使损失降到最小,求出被摧残的最小的花数。

考察
贪心(套路,经典题)

思路:
类似国王游戏那道题。交换相邻两头牛的顺序既不影响前面的牛破坏的花的数量
也不影响后面的牛破坏的花的数量。
首先构造
2a[i].tb[i].d<2a[i].db[i].t的情况,即先抱走a使结果最优的情况。
两边同时除以2a[i].db[i].d
得到a[i].t/a[i].d<b[i].t/b[i].d
设rate= a[i].t/a[i].d,只与自身有关。
显然rate越小的放前面更优。

因此按rate从小到大对序列排序。
然后就是算被被摧残的花的最小数目了。
先求出摧残的花的数目的前缀和。
由题意得,当第a[i]头牛被抱走时,后面得所有牛都有
2*a[i].t得2时间去摧残花花。

所以ans+=(sum[n]-sum[i])2a[i].t

注意数据范围,ans用ll

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+10;
struct node{
	int t,d;
	double rate;
	bool operator<(const node& x) const{
	     return rate<x.rate;
		 }
}a[N];
int sum[N];
ll ans;

int main(){
	int n;
	scanf("%d",&n);
	/*
	a[i].t*b[i].d<a[i].d*b[i].t
	a[i].t/a[i].d<b[i].t/b[i].d
	
	
	*/
	for(int i=1;i<=n;i++){
		//时间和摧残的花花 
		scanf("%d%d",&a[i].t,&a[i].d);
		a[i].rate=1.0*a[i].t/a[i].d;//这个越小放前面 
	}
	sort(a+1,a+n+1);//排序 
	for(int i=1;i<=n;i++){
		sum[i]=sum[i-1]+a[i].d;//前缀和,前面的牛摧残的花总数 
	}
	for(int i=1;i<=n;i++){
		ans+=(sum[n]-sum[i])*2*a[i].t;// a[i]这头牛被抱走了,剩下后面的所有的牛都有2*a[i].t的时间去摧残花花 
	}
	printf("%lld\n",ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值