智力竞赛(慢慢领悟dp)
来源:互联网 发布:前端与后台数据交互 编辑:程序博客网 时间:2024/05/22 12:19
#1285 : 智力竞赛
- 样例输入
12 10 9 112 35
- 样例输出
5
描述
小Hi、小Ho还有被小Hi强拉来的小Z,准备组队参加一个智力竞赛。竞赛采用过关制,共计N个关卡。在第i个关卡中,小Hi他们需要获得Ai点分数才能够进入下一关。每一关的分数都是独立计算的,即使在一关当中获得超过需要的分数,也不会对后面的关卡产生影响。
小Hi他们可以通过答题获得分数。答对一道题获得S点分数,答错一道题获得T点分数。在所有的N个关卡中,小Hi他们一共有M次答题机会。在每个关卡中,都可以在累计答题次数不超过M的情况下使用任意次的答题机会。
那么现在问题来了,对于给定的N、M、S、T和A,小Hi他们至少需要答对多少道题目才能够完成所有的关卡呢?
输入
每个输入文件包含多组测试数据,在每个输入文件的第一行为一个整数Q,表示测试数据的组数。
每组测试数据的第一行为四个正整数N、M、S和T,意义如前文所述。
第二行为N个正整数,分别表示A1~AN。
对于40%的数据,满足1<=N,M<=100
对于100%的数据,满足1<=N,M<=1000,1<=T<S<=10,1<=Ai<=50
对于100%的数据,满足1<=Q<=100
输出
对于每组测试数据,如果小Hi他们能够顺利完成关卡,则输出一个整数Ans,表示小Hi他们至少需要答对的题目数量,否则输出No。
题目链接:http://hihocoder.com/problemset/problem/1285
分析:
此题花了很长时间去思考如何定义状态。首先 “完成了多少个关卡” 这个状态是要有的,这样对于一个新的关卡可以看与前一个关卡之间的关系,从而推到完成n个关卡时的状态。然后 “总共用了多少次机会” 这个状态是否需要呢,不知道,但这个变量是条件中的一个限制,肯定要用,先试试看吧,看是否能够利用它好推出前后的状态关系。“完成当前关卡用了几次机会” 这个状态不需要,因为它的前一个状态与当前状态没有太大关系,状态不好递推。同理,“当前关卡答对几次” 、“总共答对几次” 等等状态的前一个状态与当前状态没有太大关系,不好推,所以不要。发现要定义的状态一般都是题目给的一些限制变量,而且都是些累积类状态。比如说 “总共用了多少次机会” 这个状态的值是需要每个关卡用的机会加起来的,我称之为累积类状态。而假如要用非累积类状态,比如说 “完成当前关卡用了几次机会” 这种不用累加的状态,一般都是因为此种状态的前一个状态和后一个状态有某种限制或可能产生特殊关系。
如果状态定义好了,那么就成功一大半了。接下来就是写状态转移方程。顾名思义,状态转移方程就是看状态是如何转移的(不是装逼==。是我现在的确对这个有点感觉了)。一般就是看某个状态可能从哪些状态转移(这些状态要离那个状态最近,也就是中间不经过其他状态)而来,然后得出状态之间的关系写出相应方程。
P.s 不要看我分析得好像好厉害的样子,但是我其实花了好长时间才想出来的。也算刚开始对动态规划有点领悟了吧。
code:
#include<bits/stdc++.h>using namespace std;#define INF 1<<30#define F first#define S secondtypedef long long ll;const int N = 1010;int dp[N][N]; //dp[i][j]表示花费j次机会完成i个关卡时已至少答对的题数int main(){ int Q, n, m, s, t, a[N]; scanf("%d", &Q); while(Q--) { scanf("%d%d%d%d", &n,&m,&s,&t); for(int i=1; i<=n; i++) scanf("%d", a+i); for(int i=0; i<=n; i++) for(int j=0; j<=m; j++) dp[i][j] = INF; dp[0][0] = 0; for(int i=1; i<=n; i++) { for(int j=0; j<=m; j++) { for(int x=0; x<=(a[i]/s+(a[i]%s!=0)) && x<=j; x++) {//完成当前关卡对了x个题目 int y = (a[i]-x*s)/t+((a[i]-x*s)%t!=0); if(a[i] <= x*s) y = 0; //完成当前关卡错了y个题目 if(j-x-y>=0) dp[i][j] = min(dp[i][j],dp[i-1][j-x-y]+x); //printf("x=%d y=%d dp[%d][%d]=%d\n", x,y,i,j,dp[i][j]); } } } int res = INF; for(int j=0; j<=m; j++) res = min(res,dp[n][j]); if(res == INF) puts("No"); else printf("%d\n", res); } return 0;}
- 智力竞赛(慢慢领悟dp)
- 智力竞赛(hiho145周)
- hihocoder 1285 智力竞赛 dp 类多重背包问题
- 智力竞赛抢答器
- hihocoder之智力竞赛
- 智力竞赛 编程题解析
- hihocoder 1285 智力竞赛 (类多重背包)
- 微软offer收割赛之智力竞赛
- hihoCoder | hiho一下145周 智力竞赛
- 留着以后慢慢做的树形DP(题表)
- 留着以后慢慢做的DP(题表)
- 留着以后慢慢做的数位DP(题表)
- 智力游戏(1)
- 倒水问题(智力)
- 智力研究(一)
- 智力研究(二)
- 智力游戏(常胜将军)
- 内涵(智力)
- 《React-Native系列》24、 结合Demo学习Redux框架
- 安装react-native命令和创建
- Java - static静态什么时候使用
- hdu 1561 The more, The Better(树形DP)
- 递归两个例子
- 智力竞赛(慢慢领悟dp)
- UEditor之——与SpringMVC整合
- 关于Single Number II的一些讨论
- c++ 模板类 声明和定义都放在.h文件的原因
- windows下文件共享以及通过网线在两台Windows电脑之间传数据
- Task schedule
- Linux--网络基础
- tjut 3948
- 10+ 最佳的 Node.js 教程和实例