题目描述
题目分析
根据题型分析应该可以用动态规划解决。设为第秒,剩余体力值为,且当前位置距离峡谷米时的总方案数。根据题意,状态转移方程如下:
这样定义状态的话空间复杂度为,大大超出了空间限制。观察转移方程左边变量是,右边都是,这样就可以反复覆盖,将空间复杂度降低至。
尽管如此,但时间复杂度依然超出了限制。
仔细思考后发现,当前位置距峡谷的位置能直接计算出来:,
因此简化状态,设为第秒,剩余体力值为时的总方案数,状态转移方程如下:
建立初始状态:
这就是该题与李白打酒加强版的区别。虽然变量很多,但是有一项变量能通过其他变量数学运算出来,因此只需用二维数组存储即可。
我的代码
注意这种需要对答案取模的问题,防止溢出每一步都要取模,否则很容易WA。
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int max_n = 3002;
ll dp[max_n][max_n];
int d;
int t;
int m;
int main(){
//初始化
int i;
int j;
cin >> d >> t >> m;
for(i = 0;i <= m;i++){
if((d - 1 + 2 * (m - i) > 0) && (i == m||i == m - 1)){
dp[1][i] = 1;
}else{
dp[1][i] = 0;
}
}
//动态规划
for(i = 2;i <= t;i++){
for(j = 0;j <= m;j++){
if(d - i + 2 * (m - j) > 0){
dp[i][j]= dp[i-1][j]%1000000007+dp[i-1][j+1]%1000000007;
dp[i][j] = dp[i][j]%1000000007;
}else{
dp[i][j] = 0;
}
}
}
//获得答案
int ans = dp[t][0];
cout<<ans;
return 0;
}