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

题意:

  有n道题目,每道题目的初始分数为Ai,分数每分钟减少Bi,完成此题需要Ci分钟,问在t分钟内最多能获得多少分?

思路:

  好题~

  如果没有B的话,就是一道裸的01背包的题目了。每道题目的得分为:v=A-B*g  (其中g为完成这道题目的时刻),想要用背包解的话是可以的,但是完成的次序不同的话,得分也可能受到影响。那就排个序得了,问题在于如何排序?假设已经确定要做哪些题了,则如果交换了相邻两道题的位置,对总分数是有益的,那么肯定是换了,而且他们对其他的题目完全无影响,不妨假设只有两道题要完成,现在要决定他们的完成次序。假设先完成题目1,再完成题目2,设t=C1+C2,那么总分为v1=A1-B1*C1 + A2-B2*t;如果交换次序,则总分为v2=A2-B2*C2 + A1-B1*t,那么v1<=v2时,明显有必要交换位置。

  由v1<=v2得到   A1-B1*C1 + A2-B2*t <= A2-B2*C2 + A1-B1*t

  化简得到 B1*C1 + B2*t >= B2*C2 + B1*t

  那么在排序时直接用这条式子就行了。

 1 //#include <bits/stdc++.h>
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <set>
 7 #include <deque>
 8 #include <map>
 9 #include <algorithm>
10 #include <vector>
11 #include <iostream>
12 #define pii pair<int,int>
13 #define back que[rear-1]
14 #define INF 0x3f3f3f3f
15 #define LL long long
16 #define ULL unsigned long long
17 using namespace std;
18 const double PI  = acos(-1.0);
19 const int N=1010;
20 struct node
21 {
22     int a, b, c;
23     double rate;
24 }seq[N];
25 int n, time, dp[N*3];
26 int cmp(node a,node b)
27 {
28     int t2=a.c+b.c;
29     return b.b*b.c+a.b*t2>=a.b*a.c+b.b*t2;
30 }
31 int cal()
32 {
33     sort(seq+1,seq+n+1, cmp);
34     memset(dp,-1,sizeof(dp));
35     dp[0]=0;
36     for(int i=1; i<=n; i++)
37         for(int j=time; j>=seq[i].c; j--)
38         {
39             if( dp[j-seq[i].c]<0 )   continue;
40             int v=seq[i].a - j*seq[i].b;
41             dp[j]=max( dp[j], dp[j-seq[i].c]+v );
42         }
43     int ans=0;
44     for(int i=time; i>=0; i--)
45         ans=max(ans, dp[i]);
46     return ans;
47 }
48
49 int main()
50 {
51     freopen("input.txt", "r", stdin);
52     int t;cin>>t;
53     while(t--)
54     {
55         scanf("%d%d",&n,&time);
56         for(int i=1; i<=n; i++)
57             scanf("%d%d%d", &seq[i].a,&seq[i].b,&seq[i].c);
58         cout<<cal()<<endl;
59     }
60     return 0;
61 }

AC代码

用官方题解的代码:

 1 //#include <bits/stdc++.h>
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <set>
 7 #include <deque>
 8 #include <map>
 9 #include <algorithm>
10 #include <vector>
11 #include <iostream>
12 #define pii pair<int,int>
13 #define back que[rear-1]
14 #define INF 0x3f3f3f3f
15 #define LL long long
16 #define ULL unsigned long long
17 using namespace std;
18 const double PI  = acos(-1.0);
19 const int N=1010;
20 struct node
21 {
22     int a, b, c;
23     double rate;
24 }seq[N];
25 int n, time, dp[N*3];
26 int cmp(node a,node b)
27 {
28     return a.rate>b.rate;
29 }
30 int cal()
31 {
32     sort(seq+1,seq+n+1, cmp);
33     memset(dp,-1,sizeof(dp));
34     dp[0]=0;
35     for(int i=1; i<=n; i++)
36         for(int j=time; j>=seq[i].c; j--)
37         {
38             if( dp[j-seq[i].c]<0 )   continue;
39             int v=seq[i].a - j*seq[i].b;
40             dp[j]=max( dp[j], dp[j-seq[i].c]+v );
41         }
42     int ans=0;
43     for(int i=time; i>=0; i--)
44         ans=max(ans, dp[i]);
45     return ans;
46 }
47
48 int main()
49 {
50     //freopen("input.txt", "r", stdin);
51     int t;cin>>t;
52     while(t--)
53     {
54         scanf("%d%d",&n,&time);
55         for(int i=1; i<=n; i++)
56         {
57             scanf("%d%d%d", &seq[i].a,&seq[i].b,&seq[i].c);
58             seq[i].rate=1.0*seq[i].b/seq[i].c;
59         }
60         cout<<cal()<<endl;
61     }
62     return 0;
63 }

AC代码

时间: 2024-10-05 15:41:43

HDU 5501 The Highest Mark (贪心+DP,经典)的相关文章

[2016-02-04][HDU][5501][The Highest Mark]

[2016-02-04][HDU][5501][The Highest Mark] HDU - 5501 The Highest Mark Time Limit: 1000MS Memory Limit: 131072KB 64bit IO Format: %I64d & %I64u Submit Status Description The SDOI in $2045$ is far from what it was been $30$ years ago. Each competition

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

题意:类似cf的赛制,每道题目有A,B,C三个值,A表示初始分数,B表示每分钟题的分数会减少B,C表示做这道题需要C分钟,数据保证分数不会变为负数.现在给出比赛时长,问安排做题的顺序,求最大得分. 思路:这道题是一道非常经典的题.首先很容易想到一件事,给出的题哪个先做没有先后顺序,那么在动态规划的时候,必然有前后顺序,所以要么就是状态压缩,要么就是之前就把这些题目排序了,使得后面是有序的.状压不用考虑了因为数据太大,所以我们考虑要如何排序. 现在有A1,B1,C1和A2,B2,C2这两道题,如果

POJ 2411 &amp;&amp; HDU 1400 Mondriaan&#39;s Dream (状压dp 经典题)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12341   Accepted: 7204 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

HDU 4939 Stupid Tower Defense(贪心+dp)

HDU Stupid Tower Defense 题目链接 题意:有一些塔,红塔能攻击经过他的,绿塔能攻击经过之后的,蓝塔能把经过之后的减速,求在1-n上放塔,求伤害最大值 思路:一开始以为直接贪心,绿塔最前,蓝塔中间,红塔最后就可以了,结果其实是错的 不过,红塔放最后是肯定的,这个很显然就不多证明了,是贪心的思想 然后就dp[i][j]表示放到i,前面有j个绿塔去状态转移即可 代码: #include <cstdio> #include <cstring> #include &l

HDU 2993 MAX Average Problem(斜率DP经典+输入输出外挂)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2993 题目大意:给出n,k,给定一个长度为n的序列,从其中找连续的长度大于等于k的子序列使得子序列中的平均值最小. 解题思路:斜率DP经典题, 详细分析见: NOI2004年周源的论文<浅谈数形结合思想在信息学竞赛中的应用> 还有要注意要用输入输出外挂,不是getchar()版的,是fread()版的,第一次遇到这么变态的题目- -|||. 代码: 1 #include<iostream&g

hdu 1207 汉诺塔II (DP+递推)

汉诺塔II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4529    Accepted Submission(s): 2231 Problem Description 经典的汉诺塔问题经常作为一个递归的经典例题存在.可能有人并不知道汉诺塔问题的典故.汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往

HDU 5616 Jam&#39;s balance 背包DP

Jam's balance Problem Description Jim has a balance and N weights. (1≤N≤20)The balance can only tell whether things on different side are the same weight.Weights can be put on left side or right side arbitrarily.Please tell whether the balance can me

DP经典题型:石子合并问题

本周集训专题为DP系列,一个经典的系列便是石子归并问题. (1)有N堆石子,现要将石子有序的合并成一堆,规定如下:每次只能移动相邻的2堆石子合并,合并花费为新合成的一堆石子的数量.求将这N堆石子合并成一堆的总花费最小(或最大). 这是石子归并的简化版本,石子处于一排.由于发现只能是相邻的2堆石子进行归并.我们会发现,贪心算法在此处便失去作用,局部最优解并不能带来整体最优解. 因此,不难让我们想到,此题应该采取DP(dynamic Programing)来求其最优解. 动态规划常常采取从部分整体最

hdu 4514 并查集+树形dp

湫湫系列故事——设计风景线 Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 4539    Accepted Submission(s): 816 Problem Description 随着杭州西湖的知名度的进一步提升,园林规划专家湫湫希望设计出一条新的经典观光线路,根据老板马小腾的指示,新的风景线最好能建成环形,如果没有条件建成环形,