您的位置:首页 > 其它

(水)POJ-3262 贪心,背包,比率问题

2016-05-08 22:20 239 查看
题目大意:

有n个牛在FJ的花园乱吃。

所以FJ要赶他们回牛棚。

每个牛在被赶走之前每秒吃Di个花朵。赶它回去FJ要花的时间是Ti,走回来再赶其他牛也需要Ti的时间。在被赶走的过程中牛就不能乱吃了

题目链接:点击打开链接

分析:这个题与贪心中的背包问题很像,都涉及到比率问题,按照比率来排序。背包问题中以 价值/质量 来从大到小排序,而这里我们以 D/T 来从大到小排序,以此顺序来赶牛就行了。

下面给出证明:

设di,ti,Ti分别代表编号为i(以 di / ti 从大到小依次编号)的牛每秒吃di个花朵,赶它花的时间是ti,经过Ti时间才被赶走,我们先来考虑牛1

对牛1有 d1 / t1 > dk / tk(1<k<=n),即 d1 * tk > dk * t1

①按照上面的贪心思想,则牛1肯定最先被赶走。则此时的总花费为:

d1*T1+d2*T2.......+dn*Tn = d2*T2.......+dn*Tn 因为T1=0

②若不先赶牛1,那么我们交换牛1与牛i的顺序。则此时的总花费发生了变化

1.对于牛i后面的牛,其T不变

2.对于牛1,T1' = T1+t2+t3.....+ti = t2+t3.....+ti

3.对于牛i ,Ti' = 0

4.对于编号在1到i之间的牛,Tk' = Tk+ ( ti - t1 )

所以此时的总花费为:

d1*T1'+d2*T2'...+dn*Tn' = (d2*T2.......+dn*Tn)
+ (d1*t2+d1*t3...+d1*ti) + (d2*ti+d3*ti...+di-1*ti) - (d2*t1+d3*t1...+di-1*t1)

由于 d1 * tk > dk * t1,所以 (d1*t2+d1*t3...+d1*ti-1)-(d2*t1+d3*t1...+di-1*t1)>0

所以花费2 > 花费1

以此归纳,可知这种贪心方法是正确的。

附上代码:

#include<iostream>
#include<algorithm>
using namespace std;
struct Cow{ int t, d; Cow(int a = 0, int b = 0){ t = a, d = b; } }cow[100000 + 5];
long long ans, sum;
int n;
bool cmp(Cow &a, Cow &b){ return a.d * b.t > b.d * a.t; }  //为了避免除法产生小数而引起精度误差,我们采用相乘的形式
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d%d", &cow[i].t, &cow[i].d);
sort(cow + 1, cow + n + 1, cmp);
for (int i = 1; i <= n; i++)
{
sum += cow[i - 1].t * 2;        //来回一共2倍t
ans += sum * cow[i].d;
}
printf("%lld\n", ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: