• HDU 5501 The Highest Mark


    题目链接:

    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})Ai(Ai106) 分,之后每过一分钟这道题目的分值会减少 B_iBi 分,并且保证到比赛结束时分值不会减少为负值。比如,一个人在第 xx 分钟结束时做出了第 ii 道题目,那么他/她可以得到 A_i - B_i * xAiBix 分。
    若一名选手在第 xx 分钟结束时做完了一道题目,则他/她可以在第 x+1x+1 分钟开始时立即开始做另一道题目。
    参加省队选拔的选手 dxy 具有绝佳的实力,他可以准确预测自己做每道题目所要花费的时间,做第 ii 道需要花费 C_i(C_i leq t)Ci(Cit) 分钟。由于 dxy 非常神,他会做所有的题目。但是由于比赛时间有限,他可能无法做完所有的题目。他希望安排一个做题的顺序,在比赛结束之前得到尽量多的分数。
    
    输入描述
    第一行为一个正整数 T(T leq 10)T(T10),表示数据组数(n>200n>200的数据不超过55组)。
    对于每组数据,第一行为两个正整数 n (n leq 1000)n(n1000)t (t leq 3000)t(t3000), 分别表示题目数量和比赛时间。接下来有 nn 行,每行 33 个正整数依次表示 A_i, B_i, C_iAi,Bi,Ci,即此题的初始分值、每分钟减少的分值、dxy做这道题需要花费的时间。
    
    输出描述
    对于每组数据输出一行一个整数,代表dxy这场比赛最多能得多少分
    输入样例
    1
    4 10
    110 5 9
    30 2 1
    80 4 8
    50 3 2
    
    输出样例
    88
    Hint
    dxy先做第二题,再做第一题,第一题得分为110-5*(1+9)=601105(1+9)=60,第二题得分为30-2*1=283021=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背包就可以了。

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 const int maxn = 1010;
     7 const int maxt = 3030;
     8 
     9 struct Node {
    10     int a, b, c;
    11     bool operator < (const Node& tmp) {
    12         return b*tmp.c>c*tmp.b;
    13     }
    14 }node[maxn];
    15 
    16 int N, T;
    17 int dp[maxn][maxt];
    18 
    19 int main() {
    20     int tc;
    21     scanf("%d", &tc);
    22     while (tc--) {
    23         scanf("%d%d", &N, &T);
    24         for (int i = 1; i <= N; i++) {
    25             scanf("%d%d%d", &node[i].a, &node[i].b, &node[i].c);
    26         }
    27         sort(node + 1, node + N + 1);
    28         /*
    29         for(int i = 1; i <= N; i++) printf("%d ", node[i].a);
    30         printf("
    ");
    31         */
    32         memset(dp[0], 0, sizeof(dp[0]));
    33         for (int i = 1; i <= N; i++) {
    34             for (int j = 0; j < node[i].c; j++) dp[i][j] = dp[i - 1][j];
    35             for (int j = node[i].c; j <= T; j++) {
    36                 dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - node[i].c]+node[i].a-node[i].b*j);
    37             }
    38         }
    39         int ans = 0;
    40         for (int i = 0; i <= T; i++) ans = max(ans, dp[N][i]);
    41         printf("%d
    ", ans);
    42     }
    43     return 0;
    44 }
    View Code

     优化:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 
     7 const int maxn = 1010;
     8 const int maxt = 3030;
     9 
    10 struct Node {
    11     int a, b, c;
    12     bool operator < (const Node& tmp) {
    13         return b*tmp.c>c*tmp.b;
    14     }
    15 }node[maxn];
    16 
    17 int N, T;
    18 int dp[maxt];
    19 
    20 int main() {
    21     int tc;
    22     scanf("%d", &tc);
    23     while (tc--) {
    24         scanf("%d%d", &N, &T);
    25         for (int i = 1; i <= N; i++) {
    26             scanf("%d%d%d", &node[i].a, &node[i].b, &node[i].c);
    27         }
    28         sort(node + 1, node + N + 1);
    29         memset(dp, 0, sizeof(dp));
    30         for (int i = 1; i <= N; i++) {
    31             for (int j = T; j >= node[i].c; j--) {
    32                 dp[j] = max(dp[j], dp[j - node[i].c] + node[i].a - node[i].b*j);
    33             }
    34         }
    35         int ans = 0;
    36         for (int i = 0; i <= T; i++) ans = max(ans, dp[i]);
    37         printf("%d
    ", ans);
    38     }
    39     return 0;
    40 }
    View Code

     

  • 相关阅读:
    可持久化线段树学习笔记
    GDI+学习之路
    tcpdump——分析tcp关闭4次过程
    nasm过程调用
    ios学习:NSURLConnection 和 Json数据解析
    ios学习:文件简单读写
    JSONP原理及其简单封装
    JSP使用JSTL
    JDBC
    Apache无法正常启动的原因
  • 原文地址:https://www.cnblogs.com/fenice/p/5250868.html
Copyright © 2020-2023  润新知