题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5501

The Highest Mark

 Accepts: 32
 Submissions: 193
 Time Limit: 2000/1000 MS (Java/Others)
 Memory Limit: 131072/131072 K (Java/Others)
问题描述
2045年的SD省队选拔,赛制和三十年前已是完全不同。一场比赛的比赛时间有 tt 分钟,有 nn 道题目。
第 ii 道题目的初始分值为 A_i(A_i \leq 10^{6})A​i​​(A​i​​≤10​6​​) 分,之后每过一分钟这道题目的分值会减少 B_iB​i​​ 分,并且保证到比赛结束时分值不会减少为负值。比如,一个人在第 xx 分钟结束时做出了第 ii 道题目,那么他/她可以得到 A_i - B_i * xA​i​​−B​i​​∗x 分。
若一名选手在第 xx 分钟结束时做完了一道题目,则他/她可以在第 x+1x+1 分钟开始时立即开始做另一道题目。
参加省队选拔的选手 dxy 具有绝佳的实力,他可以准确预测自己做每道题目所要花费的时间,做第 ii 道需要花费 C_i(C_i \leq t)C​i​​(C​i​​≤t) 分钟。由于 dxy 非常神,他会做所有的题目。但是由于比赛时间有限,他可能无法做完所有的题目。他希望安排一个做题的顺序,在比赛结束之前得到尽量多的分数。
输入描述
第一行为一个正整数 T(T \leq 10)T(T≤10),表示数据组数(n>200n>200的数据不超过55组)。
对于每组数据,第一行为两个正整数 n (n \leq 1000)n(n≤1000) 和 t (t \leq 3000)t(t≤3000), 分别表示题目数量和比赛时间。接下来有 nn 行,每行 33 个正整数依次表示 A_i, B_i, C_iA​i​​,B​i​​,C​i​​,即此题的初始分值、每分钟减少的分值、dxy做这道题需要花费的时间。
输出描述
对于每组数据输出一行一个整数,代表dxy这场比赛最多能得多少分
输入样例
1
4 10
110 5 9
30 2 1
80 4 8
50 3 2
输出样例
88
Hint
dxy先做第二题,再做第一题,第一题得分为110-5*(1+9)=60110−5∗(1+9)=60,第二题得分为30-2*1=2830−2∗1=28,总得分为8888,其他任何方案的得分都小于8888

题解:

  贪心+01背包。

贪心:

  假设比赛时间无限大,每一道题目都能做完,那么你按照bi/ci由大到小排序的顺序完成所有题目会得到优成绩,

  为什么呢?

    任意两个相邻的题目i和j(i<j),先做i,你会损失分数:ci*bj;先做j,你会损失cj*bi,如果我们要先完成i,则有ci*bj<=cj*bi,即bi/ci>=bj/cj。

  现在考虑有限时间内,如果最优解中的几个问题不是按照这个顺序来完成的,那么我们经过以上操作调整之后能使损失减小,从而得到更优解。

  所以这个贪心是正确的。

dp:

  贪心完之后,跑一遍01背包就可以了。

代码:

 #include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std; const int maxn = ;
const int maxt = ; struct Node {
int a, b, c;
bool operator < (const Node& tmp) {
return b*tmp.c>c*tmp.b;
}
}node[maxn]; int N, T;
int dp[maxn][maxt]; int main() {
int tc;
scanf("%d", &tc);
while (tc--) {
scanf("%d%d", &N, &T);
for (int i = ; i <= N; i++) {
scanf("%d%d%d", &node[i].a, &node[i].b, &node[i].c);
}
sort(node + , node + N + );
/*
for(int i = 1; i <= N; i++) printf("%d ", node[i].a);
printf("\n");
*/
memset(dp[], , sizeof(dp[]));
for (int i = ; i <= N; i++) {
for (int j = ; j < node[i].c; j++) dp[i][j] = dp[i - ][j];
for (int j = node[i].c; j <= T; j++) {
dp[i][j] = max(dp[i - ][j], dp[i - ][j - node[i].c]+node[i].a-node[i].b*j);
}
}
int ans = ;
for (int i = ; i <= T; i++) ans = max(ans, dp[N][i]);
printf("%d\n", ans);
}
return ;
}

优化:

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std; const int maxn = ;
const int maxt = ; struct Node {
int a, b, c;
bool operator < (const Node& tmp) {
return b*tmp.c>c*tmp.b;
}
}node[maxn]; int N, T;
int dp[maxt]; int main() {
int tc;
scanf("%d", &tc);
while (tc--) {
scanf("%d%d", &N, &T);
for (int i = ; i <= N; i++) {
scanf("%d%d%d", &node[i].a, &node[i].b, &node[i].c);
}
sort(node + , node + N + );
memset(dp, , sizeof(dp));
for (int i = ; i <= N; i++) {
for (int j = T; j >= node[i].c; j--) {
dp[j] = max(dp[j], dp[j - node[i].c] + node[i].a - node[i].b*j);
}
}
int ans = ;
for (int i = ; i <= T; i++) ans = max(ans, dp[i]);
printf("%d\n", ans);
}
return ;
}

HDU 5501 The Highest Mark的更多相关文章

  1. HDU 5501 The Highest Mark 背包dp

    The Highest Mark Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?p ...

  2. HDU 5501——The Highest Mark——————【贪心+dp】

    The Highest Mark Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Other ...

  3. hdu 5501 The Highest Mark(贪心+01背包)

    题意:类似cf的赛制,每道题目有A,B,C三个值,A表示初始分数,B表示每分钟题的分数会减少B,C表示做这道题需要C分钟,数据保证分数不会变为负数.现在给出比赛时长,问安排做题的顺序,求最大得分. 思 ...

  4. HDU 5501 The Highest Mark (贪心+DP,经典)

    题意: 有n道题目,每道题目的初始分数为Ai,分数每分钟减少Bi,完成此题需要Ci分钟,问在t分钟内最多能获得多少分? 思路: 好题~ 如果没有B的话,就是一道裸的01背包的题目了.每道题目的得分为: ...

  5. HDU 5501:The Highest Mark 01背包

    The Highest Mark  Accepts: 71  Submissions: 197  Time Limit: 2000/1000 MS (Java/Others)  Memory Limi ...

  6. The Highest Mark(01背包)

    The Highest Mark Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Other ...

  7. HDU5501/BestCoder Round #59 (div.2)The Highest Mark dp+贪心

    The Highest Mark 问题描述 2045年的SD省队选拔,赛制和三十年前已是完全不同.一场比赛的比赛时间有 tt 分钟,有 nn 道题目. 第 ii 道题目的初始分值为 A_i(A_i \ ...

  8. hdu5501 The Highest Mark

    Problem Description The SDOI in 2045 is far from what it was been 30 years ago. Each competition has ...

  9. HDU 5501 背包问题

    需要按照B/C的值从大到小排序. #include<cstdio> #include<cstring> #include<iostream> #include< ...

随机推荐

  1. node 借助Node Binary管理模块“n”更新

    Node.js的版本频繁变化,如果有模块不能在你当前的Node版本上使用,需要升级Node环境 1)首先:查看当前node版本:node –v 2)安装n模块:npm install -g n 3)检 ...

  2. 一图看懂JVM,JRE,JDK的关系

  3. python 运算符与分支结构

    运算符与分支结构 运算符 赋值运算符 用'='表示,左边只能是变量 算术运算符 +.-.*:加.减.乘 /:除法运算,结果是浮点型 //:除法运算,结果是整型 %:求余 **:求幂 复合运算符 +=. ...

  4. SpringBoot 启动报The Java Virtual Machine has not been configured to use the desired default character encoding (UTF-8)

    解决方法: 启动的时候在VM中添加 Dfile.encoding=UTF-8 就好了!

  5. python2.7入门---XML解析

        首先我们先来考虑,什么是XML?XML 指可扩展标记语言(eXtensible Markup Language).XML 被设计用来传输和存储数据.XML是一套定义语义标记的规则,这些标记将文 ...

  6. 一些有趣的 Shell 命令

    find . -name "*.db" -type f 查找当前路径下名称满足正则*.db的文件,-type d 则是查找文件夹 grep -rn "Main" ...

  7. SWT_之Table篇

    package edu.ch4; import org.eclipse.swt.SWT;import org.eclipse.swt.events.SelectionAdapter;import or ...

  8. # 第二周c实践所遇见的问题

    第二周c实践所遇见的问题 地址符 在编程练习中时常忘记写入地址符,造成过运行错误,运行结果错误的惨痛教训,一个小小的错误耗费了很长的时间来寻找错误之处,养成写代码的一些好习惯势在必行.牢记scanf( ...

  9. 【洛谷P4556】 雨天的尾巴

    题面 题解 线段树合并 我们看到这道题目首先可以想到树上差分,然后\(dfs\)合并 发现题目让我们求的东西很好用线段树维护 于是可以想到线段树合并 全世界只有我写指针版动态开点线段树(大雾 如果你要 ...

  10. 1135: [POI2009]Lyz

    1135: [POI2009]Lyz https://lydsy.com/JudgeOnline/problem.php?id=1135 分析: hall定理+线段树连续区间的最大的和. 首先转化为二 ...