HDU 5501 The Highest Mark【背包+贪心】

2024-01-17 00:38
文章标签 贪心 背包 hdu mark highest 5501

本文主要是介绍HDU 5501 The Highest Mark【背包+贪心】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参看资料:

https://blog.csdn.net/rain722/article/details/75418642


题目:

The SDOI in 20452045 is far from what it was been 3030 years ago. Each competition has ttminutes and nn problems. 

The ithith problem with the original mark of Ai(Ai≤106)Ai(Ai≤106),and it decreases BiBi by each minute. It is guaranteed that it does not go to minus when the competition ends. For example someone solves the ithith problem after xx minutes of the competition beginning. He/She will get Ai−Bi∗xAi−Bi∗x marks. 

If someone solves a problem on xx minute. He/She will begin to solve the next problem on x+1x+1 minute. 

dxy who attend this competition with excellent strength, can measure the time of solving each problem exactly.He will spend Ci(Ci≤t)Ci(Ci≤t) minutes to solve the ith problem. It is because he is so godlike that he can solve every problem of this competition. But to the limitation of time, it's probable he cannot solve every problem in this competition. He wanted to arrange the order of solving problems to get the highest mark in this competition. 

Input

There is an positive integer T(T≤10)T(T≤10) in the first line for the number of testcases.(the number of testcases with n>200n>200 is no more than 55) 

For each testcase, there are two integers in the first line n(1≤n≤1000)n(1≤n≤1000) and t(1≤t≤3000)t(1≤t≤3000) for the number of problems and the time limitation of this competition. 

There are nn lines followed and three positive integers each line Ai,Bi,CiAi,Bi,Ci. For the original mark,the mark decreasing per minute and the time dxy of solving this problem will spend. 

Hint: 
First to solve problem 22 and then solve problem 11 he will get 8888 marks. Higher than any other order.

Output

For each testcase output a line for an integer, for the highest mark dxy will get in this competition.

Sample Input

1
4 10
110 5 9
30 2 1
80 4 8
50 3 2

Sample Output

88

题目大意:

给定时间 t ;有n道题目,对于题目i,有一个初始得分Ai,有一个每分钟掉分值 Bi,即在第x分 解出题目 i ,则可以得到的分数为Ai - Bi*x ; 现在有一个人,知道自己完成每一道题需要的时间,现在求合理安排做题顺序后该选手可以得到的最大分数。

解题思路:

一眼就明白了背包背在哪里,时间;然后贪心贪在哪里,总得分最大,当时没有深想,dp不就是为了解决贪心目光短浅的问题吗?但是这个先后规则,,怎么弄,,出于对dp的敬畏还有做不出题的难受,跳了过去。

挺同学讲了讲,看了看题解,慢慢明白了这个题优先选择的方式:

给出的题哪个先做没有先后顺序,那么在动态规划的时候,必然有前后顺序,所以要么就是状态压缩,要么就是之前就把这些题目排序了,使得后面是有序的。状压不用考虑了因为数据太大,所以我们考虑要如何排序。

现在有A1,B1,C1和A2,B2,C2这两道题,如果先做1再做2的得分是A1-B1*C1+A2-B2*(C1+C2),如果先做2在做1的得分是A2-B2*C2+A1-B1*(C1+C2),令先做1再做2的得分更高些,那么有A1-B1*C1+A2-B2*(C1+C2) >= A2-B2*C2+A1-B1*(C1+C2),解得B1*C2>=B2*C1【化简后】

所以,只要B1*C2>=B2*C1,那么先做题1再做题2的分数就会更高。【给出选择规则,至于最终的最高分是多少,交给dp来做】

所以,我们只需要根据这个来排序,再做dp,就能得到答案了。

实现代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1005;
struct Ploblem
{int a,b,c;bool operator < (const Ploblem &other) const    //排序规则{return b*other.c > other.b*c;}
}p[maxn];int dp[3005];
int main(){int T, n, t;scanf("%d", &T);while(T--){scanf("%d%d",&n,&t);for(int i=1;i<=n;i++)       //输入scanf("%d%d%d",&p[i].a,&p[i].b,&p[i].c);memset(dp, 0, sizeof(dp));  //初始化sort(p+1, p+n+1);           //排序,结构体内有排序规则int ans=0;for(int i=1;i<=n;i++)for(int j=t;j>=p[i].c;j--){dp[j]=max(dp[j],dp[j-p[i].c]+(p[i].a-p[i].b * j));ans = max(ans, dp[j]);}printf("%d\n", ans);}return 0;
}

 

这篇关于HDU 5501 The Highest Mark【背包+贪心】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/614425

相关文章

poj2576(二维背包)

题意:n个人分成两组,两组人数只差小于1 , 并且体重只差最小 对于人数要求恰好装满,对于体重要求尽量多,一开始没做出来,看了下解题,按照自己的感觉写,然后a了 状态转移方程:dp[i][j] = max(dp[i][j],dp[i-1][j-c[k]]+c[k]);其中i表示人数,j表示背包容量,k表示输入的体重的 代码如下: #include<iostream>#include<

hdu2159(二维背包)

这是我的第一道二维背包题,没想到自己一下子就A了,但是代码写的比较乱,下面的代码是我有重新修改的 状态转移:dp[i][j] = max(dp[i][j], dp[i-1][j-c[z]]+v[z]); 其中dp[i][j]表示,打了i个怪物,消耗j的耐力值,所得到的最大经验值 代码如下: #include<iostream>#include<algorithm>#include<

csu(背包的变形题)

题目链接 这是一道背包的变形题目。好题呀 题意:给n个怪物,m个人,每个人的魔法消耗和魔法伤害不同,求打死所有怪物所需的魔法 #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>//#include<u>#include<map

hdu1011(背包树形DP)

没有完全理解这题, m个人,攻打一个map,map的入口是1,在攻打某个结点之前要先攻打其他一个结点 dp[i][j]表示m个人攻打以第i个结点为根节点的子树得到的最优解 状态转移dp[i][ j ] = max(dp[i][j], dp[i][k]+dp[t][j-k]),其中t是i结点的子节点 代码如下: #include<iostream>#include<algorithm

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

usaco 1.3 Barn Repair(贪心)

思路:用上M块木板时有 M-1 个间隙。目标是让总间隙最大。将相邻两个有牛的牛棚之间间隔的牛棚数排序,选取最大的M-1个作为间隙,其余地方用木板盖住。 做法: 1.若,板(M) 的数目大于或等于 牛棚中有牛的数目(C),则 目测 给每个牛牛发一个板就为最小的需求~ 2.否则,先对 牛牛们的门牌号排序,然后 用一个数组 blank[ ] 记录两门牌号之间的距离,然后 用数组 an

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s