首页 > 代码库 > hdu 4882 ZCC Loves Codefires (贪心 推导)
hdu 4882 ZCC Loves Codefires (贪心 推导)
题目链接
做题的时候凑的规律,其实可以 用式子推一下的。
题意:n对数,每对数有e,k, 按照题目的要求(可以看下面的Hint就明白了)求最小的值。
分析:假设现在总的是sum, 有两个e1 k1 e2 k2
则先选e1 为 (sum+e1)*k1+(sum+e1+e2)*k2
先e2: (sum+e2)*k2 + (sum+e1+e2)*k1.
比较两个式子发现不同的部分分别是 e1*k2 e2*k1; 比较大小移向 e1/k1 e2/k2, 那个小,就选那个,能达到最小。
官方题解:
考察序列中相邻的两题i, j(i在前)。交换它们后,解出它们之前的题目所带来的时间对答案的贡献是不变的,它们对
它们后面的题目的贡献也是不变的,其他题目之间对答案的贡献自然也是不变的。唯一的变化就是,原来的EiKj一项变
成了EjKi一项。那么,为了使答案变优,需要满足的条件是EjKi≤EiKj。也即Ei/Ki≥Ej/Kj。
那么,最优解序列Ai一定满足,EAi/KAi是递增的。
排序一遍即可。
1 #include <stdio.h> 2 #include <iostream> 3 #include <string.h> 4 #include <stdlib.h> 5 #include <algorithm> 6 using namespace std; 7 const int maxn = 100000+10; 8 int n; 9 struct node10 {11 int e, k;12 double x;13 }p[maxn];14 15 bool cmp(node a, node b)16 {17 return a.x < b.x;18 }19 int main()20 {21 int i;22 __int64 sum, ans;23 while(~scanf("%d", &n))24 {25 for(i = 0; i < n; i++)26 {27 scanf("%d", &p[i].e);28 }29 for(i = 0; i < n; i++)30 {31 scanf("%d", &p[i].k);32 p[i].x = (double)(p[i].e*1.0/p[i].k*1.0);33 }34 sort(p, p+n, cmp);35 sum = 0; ans = 0;36 for(i = 0; i < n; i++)37 {38 sum += p[i].e;39 ans += sum*p[i].k;40 }41 cout<<ans<<endl;42 }43 return 0;44 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。