(水)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
以此归纳,可知这种贪心方法是正确的。
附上代码:
有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; }
相关文章推荐
- 网站的高性能架构---Web前端性能优化
- 20145232 韩文浩 《Java程序设计》第10周学习总结
- 20145303刘俊谦 《Java程序设计》第十周学习总结
- 20159313网络攻击与防范第十周学习总结
- Android自定义View的一般步骤
- UESTC - 1041 Hug the princess(位运算&转换)好题
- 多栈共享技术,双端栈的初始化、进栈、出栈操作
- Matrix变换矩阵的探索(1)
- iphone SE 自带视频播放器要求的视频格式转换参数
- 算法 笔记1 时间复杂度计算
- 轨迹聚类分析问题
- HDU 3757 dp
- Xftp5中文文件乱码
- 20145322《Java程序设计》第5次实验报告
- 使用 Intel HAXM 为 Android 模拟器加速,媲美真机
- discuz和phpwind哪个好
- Fragment中的onActivityResult方法不调用
- 解决ubuntu下Android Studio出现“aapt” IOException error=2, No such file or directory问题
- Linux命令缩写的解释
- 剑指offer刷题—斐波那契数列