题目大意:
有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; }