Problem Statement |
|||||||||||||
|
TypoCoder is a programming contest like TopCoder. TypoCoder also has a rating system. There are two types of coders in TypoCoder: brown coders and ciel coders. A brown coder is a coder whose rating is greater than or equal to 2200. A ciel coder is a coder whose rating is less than 2200. |
||||||||||||
Definition |
|||||||||||||
|
|
||||||||||||
Limits |
|||||||||||||
|
|
||||||||||||
Constraints |
|||||||||||||
- |
D will contain between 1 and 50 elements, inclusive. |
||||||||||||
- |
Each element of D will be between 0 and 1,000,000,000 (10^9), inclusive. |
||||||||||||
- |
X will be between 0 and 2199, inclusive. |
||||||||||||
Examples |
|||||||||||||
0) |
|
||||||||||||
|
|
||||||||||||
1) |
|
||||||||||||
|
|
||||||||||||
2) |
|
||||||||||||
|
|
||||||||||||
3) |
|
||||||||||||
|
|
||||||||||||
4) |
|
||||||||||||
|
|
||||||||||||
5) |
|
||||||||||||
|
|
||||||||||||
6) |
|
||||||||||||
|
|
类型:dp 难度:2.5
题意:给出一个初始分数X,以及一个数组D,表示每次比赛的分值,按顺序进行比赛,若赢则当前分数加上本次比赛分数,若输则减去,每次分数大于等于2200时,必须在下一次比赛(如果有的话)回到2200一下,分值小于0时,记为0,求分数最多越过2200几次。(如1900->2200,越过2200一次,2200->2199,也算越过2200一次)
分析:一开始考虑为dp,但是因为超过2200的部分,其得分范围可能很大,所以放弃了dp,采用搜索的方法,但是会超时,后来发现,实际上是可以用dp的,因为每次超过2200时,下一回合必须回到2200一下,所以直接跳过一个状态即可,用dp[i][j]记录第i次比赛,当前分值为j时,分数越过2200的最大次数。
遍历每次比赛,每次比赛遍历上一次比赛在0-2200中可能的取值,然后更新本次比赛可能的取值,即dp[i][j] = max(dp[i-1][k]),其中j = k+D[i]或k-D[i]
若k+D[i]>=2200,即加上当前比赛分数后,分值超过2200,那么再分情况讨论:
1、若k+D[i]-D[i+1]<2200,即在下一回合能回到2200一下,合法,那么dp[i+1] = 2+dp[i-1][k]
2、若k+D[i]-D[i+1]>=2200,非法,舍弃
3、若i为最后一次比赛,则dp[i] = 1+dp[i-1][k]
注意:由于k-D[i]有可能小于0,注意将其重置为0,防止数组越界
代码:
#include<iostream> #include<cstring> #include<cstdio> #include<string> #include<vector> using namespace std; int dp[60][2210]; class TypoCoderDiv1 { private: vector<int> d; public: int mmax(int a,int b) { return a>b?a:b; } int getmax(vector <int> D, int X) { d.assign(D.begin(),D.end()); memset(dp,-1,sizeof(dp)); dp[0][X] = 0; for(int i=0; i<d.size(); i++) { for(int j=0; j<2200; j++) { if(dp[i][j]>=0) { int nowa = j+d[i]; int nowb = j-d[i]; if(nowa>=2200) { if(i+1<d.size()) { int tmp = nowa-d[i+1]; if(tmp<2200) { if(tmp<0) tmp = 0; dp[i+2][tmp] = mmax(dp[i+2][tmp],dp[i][j]+2); } } else { dp[i+1][j] = mmax(dp[i+1][j],dp[i][j]+1); } } else { dp[i+1][nowa] = mmax(dp[i+1][nowa],dp[i][j]); } if(nowb<0) nowb = 0; dp[i+1][nowb] = mmax(dp[i+1][nowb],dp[i][j]); } } } int ans = 0; for(int i=0; i<2200; i++) ans = mmax(ans,dp[d.size()][i]); return ans; } }; int main() { TypoCoderDiv1 t; int a[] = {1000000000,1000000000,10000,100000,2202,1}; vector<int> b; for(int i=0; i<6; i++) b.push_back(a[i]); cout<<t.getmax(b,1000)<<endl; }