博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CF277D Google Code Jam
阅读量:4622 次
发布时间:2019-06-09

本文共 2185 字,大约阅读时间需要 7 分钟。

\(n\) 道题目,每道题分为小题目和大题目,只有做完了小题目才能做大题目,提交结果会在比赛结束后得知。其中,做第 \(i\) 个小题目需要 \(ScoreSmall_i\) 分钟,可以获得得分 \(TimeSmall_i\) ;做第 \(i\) 个大题目需要 \(ScoreLarge_i\) 分钟,可以获得得分 \(TimeLarge_i\) 。每个小题目可以一遍过,第 \(i\) 个大题目有 \(ProbFail_i\) 的几率错误,总罚时是 最后一次正确提交的时间。现在你有 \(t\) 分钟,求在这 \(t\) 分钟内你最多期望能够获得多少分,并且在满足得分最多的情况下使得罚时最小。

\(n\leq1000;t,\ TimeSmall_i,\ TimeLarge_i\in[1,\ 1560];\ ScoreSmall_i,\ ScoreLarge_i\in[1,\ 10^9];\ 0\leq ProbFail_i\leq 1\)

dp,贪心,概率


背包可以解决最高得分,那么现在要找到一种最优的顺序使得罚时最低。

可以发现 \(Small\) 对罚时没有特殊影响,可以直接计算。假设需要解决两道题 \(i,\ j\)\(Large\) ,令 \(t_i=TimeLarge_i,\ p_i=ProbFail_i\),若 \(i\) 排在 \(j\) 之前,罚时为 \((1-p_j)(t_i+t_j)+t_i(1-p_i)p_j\)

化式子得,若 \(i\) 排在 \(j\) 之前的得分大于 \(j\) 排在 \(i\) 之前当且仅当 \(t_i\times p_i/(1-p_i)>t_j\times p_j/(1-p_j)\)

按照这个规则排序即可。

代码

#include 
using namespace std;typedef long double db;const db eps = 1e-15;const int maxn = 2010;int n, m;db dp[maxn], val[maxn];struct node { int v1, v2, t1, t2; db p; inline bool operator < (const node &o) const { return t2 * p / (1 - p) < o.t2 * o.p / (1 - o.p); }} a[maxn];int main() { scanf("%d %d", &n, &m); for (int i = 1; i <= n; i++) { double f; scanf("%d %d %d %d %lf", &a[i].v1, &a[i].v2, &a[i].t1, &a[i].t2, &f); a[i].p = f; } sort(a + 1, a + n + 1); for (int i = 1; i <= m; i++) { dp[i] = -1e18, val[i] = 1e18; } for (int i = 1; i <= n; i++) { db p = a[i].p, tmp1, tmp2; int v1 = a[i].v1, v2 = a[i].v2; int t1 = a[i].t1, t2 = a[i].t2; for (int j = m; j >= t1; j--) { tmp1 = dp[j - t1] + v1, tmp2 = val[j - t1] + t1; if (dp[j] < tmp1 || (fabs(dp[j] - tmp1) < eps && val[j] > tmp2)) { dp[j] = tmp1, val[j] = tmp2; } if (j < t1 + t2) continue; tmp2 = dp[j - t1 - t2] + v1 + (1 - p) * v2; tmp1 = t1 + (1 - p) * (j - t1) + p * val[j - t1 - t2]; if (dp[j] < tmp2 || (fabs(dp[j] - tmp2) < eps && val[j] > tmp1)) { dp[j] = tmp2, val[j] = tmp1; } } } int pos = 0; for (int i = 1; i <= m; i++) { if (dp[pos] < dp[i] || (fabs(dp[pos] - dp[i]) < eps && val[i] < val[pos])) { pos = i; } } printf("%.10lf %.10lf", (double) dp[pos], (double) val[pos]); return 0;}

转载于:https://www.cnblogs.com/Juanzhang/p/11334597.html

你可能感兴趣的文章
Zookeeper要安装在奇数个节点,但是为什么?
查看>>
discuz 微社区安装记录
查看>>
[BZOJ4824][Cqoi2017]老C的键盘 树形dp+组合数
查看>>
配置的热更新
查看>>
MySQL事务的开启与提交,autocommit自动提交功能
查看>>
PriorityQueue
查看>>
CODEVS1403 新三国争霸
查看>>
iOS 环信离线推送
查看>>
WPFTookit Chart 高级进阶
查看>>
thulac安装问题
查看>>
你必须知道的.NET Day1
查看>>
vim实现实时自动保存
查看>>
mysql CREATE USER
查看>>
H3C 快速以太网和千兆以太网
查看>>
oracle触发器——ddl触发器
查看>>
oracle函数 SOUNDEX(c1)
查看>>
spring-data-elasticsearch使用出现的一些小问题
查看>>
雷云Razer Synapse2.0使用测评 -第二次作业
查看>>
Android ProgressBar手动控制开始和停止
查看>>
【iCore3 双核心板】DEMO 1.0 测试程序发布
查看>>