SRM 502 DIV1 500pt(DP)

题目简述

给定比赛时间T和n个题目,你可以在任意时间提交题目,每个题目有一个初始分数maxPoints[i],每个单位时间题目的分数将会减少pointsPerMinute[i],即如果在时间t解决了第i个题目,那么获得的分数为maxPoints[i] - t * pointsPerMinute[i],另外做每个题目需要requiredTime[i]的时间,求能够获得的最大分数是多少?

题解

由于问题解决的先后,获得的分数是不一样的,因为我们首先得确定做题的选择顺序,根据相邻交换法,对于问题a和问题b,如果requiredTime[b]*pointsPerMinute[a]>requiredTime[a]*pointsPerMinute[b],先解决a再解决b获得的分数会比先b后a多,所以我们可以先根据这个条件对题目进行排序,之后就是01背包问题了

代码:

 1 struct node
 2 {
 3     int mp, pp, rt;
 4 };
 5 node a[55];
 6 int  dp[100005];
 7 bool cmp(node a, node b)
 8 {
 9     return (LL)b.rt * a.pp > (LL)a.rt * b.pp;
10 }
11 class TheProgrammingContestDivOne
12 {
13 public:
14     LL find(int T, vector <int> maxPoints, vector <int> pointsPerMinute, vector <int> requiredTime)
15     {
16         int n = maxPoints.size();
17         for (int i = 0; i < n; i++)
18         {
19             a[i + 1].mp = maxPoints[i];
20             a[i + 1].pp = pointsPerMinute[i];
21             a[i + 1].rt = requiredTime[i];
22         }
23         sort(a + 1, a + n + 1, cmp);
24         memset(dp, 0, sizeof(dp));
25         for (int i = 1; i <= n; i++)
26             for (int j = T; j >= a[i].rt; j--)
27                 if (a[i].mp - (LL)a[i].pp * j >=0)
28                     dp[j] = max(dp[j], dp[j - a[i].rt] + a[i].mp - a[i].pp * j);
29         int ans = 0;
30         for (int i = 0; i <= T; i++) ans = max(ans, dp[i]);
31         return ans;
32     }
33 };
时间: 2024-10-06 21:38:03

SRM 502 DIV1 500pt(DP)的相关文章

SRM 514 DIV1 500pt(DP)

题目简述 给定一个H×W大小的矩阵,每个格子要么是1~9中的一个数,要么是".",要求你把“.”填成具体的数字(1~9),并且符合以下两个要求: 对于所有的整数r 和 c( 0 <= r <= H-n,0 <= c < W), 使得 F[r][c] + F[r+1][c] + ... + F[r+n-1][c] 是奇数. 对于所有的整数 r 和c(0 <= r < H,0 <= c <= W-m), 使得 F[r][c] + F[r][c

SRM 508 DIV1 500pt(DP)

题目简述 给定一个大小为 n的序列(n<=10)R,要求你计算序列A0, A1, ..., AN-1的数量,要求A序列满足A0 + A1 + ... + AN-1 = A0 | A1 | ... | AN-1(0<=Ai<=R[i]) 题解 把n个数看成二进制,如果要求n个数的和等于n个数的或值,那么对于n个数的每一位,最多只可能有一个1,因为超过一个一就会产生进位. 由于第i个数如果当前位放置的是0,但 R[i]的当前位是1,那么之后的位置上就可以随意放了,没有限制,所以我们可以用DP

SRM 509 DIV1 500pt(DP)

题目简述 给定一个字符串,可以对其进行修改,删除,增加操作,相应的操作有对应的花费,要求你用最小的花费把字符串变为回文串 题目做法 先搞一遍floyed把各种操作的最小花费求出来,然后就是类似编辑距离的DP了,这题坑了好久...中间结果会爆int,我设置的inf=0x3f3f3f3f,中间结果有inf+inf+inf..刚开始dp数组是int型的...这里搞了好几才发现这问题...西安现场赛也遇到这个问题了...然后也是浪费了将近100分钟的时间...导致后面做题的时间不够了... 代码: 1

SRM 511 DIV1 500pt(DP)

题目简述 给定n个数,两个人轮流取数,和之前两个人的取的数或起来,谁不能取数或者谁取到的数和之前的数或值为511谁输,问谁能够赢? 题解 刚开始的想法是直接搜,不过需要记录取过的值的状态,2^50显然超时...对于当前或值cur,或上一个数num,只有两种情况,要么是 cur|num==cur, 对于这种数,只是把这个状态直接给下一个玩家,起到延缓一步的作用,他们的选取顺序对局面没有影响,可以先全部轮流取掉,如果这种数的个数大于当前已经取的数的数量,那么我们还可以选择这种数,如果选择这个数可以导

SRM 618 DIV1 500

非常棒的组合问题,看了好一会,无想法.... 有很多做法,我发现不考虑顺序的最好理解,也最好写. 结果一定是两种形式 A....A   dp[n-1] A...A...A sgma(dp[j]*dp[n-j-1])( 1<=j<=n-2) 最后乘上n! 什么时候才能自己在比赛中做出一个500分来啊!!! class LongWordsDiv1 { public : int count(int n) { int i,j; fact[0] = 1; for(i = 1; i <= n; i

Topcoder SRM 643 Div1 250&lt;peter_pan&gt;

Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*......*pn,我们假设p0,p1,...,pn是单调不降的,那么v里存储的是下标为偶数 的N的质因数p0,p2,p4,...,p(2k).现在要求写一个程序,返回一个vector<long long>ans; ans里存储的是p0,p1,p2,...,pn. Limits Time Limit(m

SRM 631 DIV1

SRM 631 DIV1 A:最多肯定只需要两步,中间的两行,一行黑,一行白就可以了,这样的话,只需要考虑一开始就满足,和枚举一行去染色满足的情况就可以了,暴力即可 B:贪心,一个记录当前有猫的位置和当前超过一只猫的位置,然后位置排序从左往右找,如果当前能移动到之前超过两只的位置,就全部移动过去,不增加,如果不行,那么考虑当前这个能不能铺成一条,如果可以,相应更新位置,如果不行,就让猫全部堆到右边右边去,然后堆数多1 代码: A: #include <iostream> #include &l

SRM 622 div1 250

Problem Statement    In the Republic of Nlogonia there are N cities. For convenience, the cities are numbered 0 through N-1. For each two different cities i and j, there is a direct one-way road from i to j. You are given the lengths of those roads a

SRM 587 DIV1

550 结论:同一层的交点共线. 很容易猜到,也可以跑几组数据验证. 利用结论就可以按层算,再利用对称性简化计算. 1 using namespace std; 2 #define maxn 70100 3 class TriangleXor { 4 public: 5 int theArea(int); 6 }; 7 double l[maxn] , x[maxn] , y[maxn] , H; 8 int idx; 9 10 void addpoint(double k,double w)