呜呜dp菜鸡终于自己独立做出来一道黄题dp呜呜
上午英语课就在上面想方程推方程,果然推的没错呜呜
前排提示,本方法纯硬dp,不带其他题解的分析用哪种方法更优,而且如果不开o2,会t两个点
现在大学生比赛应该都开o2的吧
状态表示:
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示在
i
i
i时间内,还剩
j
j
j点法力值所走的最远距离是多少
状态计算:注意,我设还剩j点法力值,所以当前的状态是
f
[
i
]
[
j
]
f[i][j]
f[i][j]的转移的时候应当注意
- 当我们选择直接步行:
f
[
i
]
[
j
]
=
f
[
i
?
1
]
[
j
]
+
17
f[i][j]=f[i-1][j]+17
f[i][j]=f[i?1][j]+17,因为不消耗体力
- 当我们选择不走回复魔法:
f
[
i
]
[
j
]
=
f
[
i
?
1
]
[
j
?
4
]
f[i][j]=f[i-1][j-4]
f[i][j]=f[i?1][j?4],因为我们现在法力是
j
j
j,那么我们恢复前就是
j
?
4
j-4
j?4
- 当我们选择瞬移:$ f[i][j] = f[i-1][j+10]$,跟上一条分析类似
那么我们就可以来进行dp了qwq
Code
#pragma GCC optimize (2)
int m, s, t;
int f[2][1020];
void solve(){
cin >> m >> s >> t;
int time = 0;
for (int i = 1; i <= t; i++){
for (int j = 0; j <= m; j++){
f[i & 1][j] = f[(i - 1) & 1][j] + 17;
if(j >= 4)
f[i & 1][j] = max(f[i & 1][j], f[(i - 1) & 1][j - 4]);
if(j + 10 <= m)
f[i & 1][j] = max(f[i & 1][j], f[(i - 1) & 1][j + 10] + 60);
if(f[i & 1][j] >= s){
if(!time){
time = i;
}
}
}
}
int res = 0;
for (int i = 0; i <= m; i++){
res = max(res, f[t & 1][i]);
}
if(res >= s){
cout << "Yes" << endl;
cout << time;
}
else{
cout << "No" << endl;
cout << res;
}
}
|