题目描述
在梦境中,你踏上了一只木筏,在江上漂流。
根据对当地的了解,你知道在你下游 D 米处有一个峡谷,如果你向下游前进大于等于 D 米则必死无疑。
现在你打响了急救电话,T 秒后救援队会到达并将你救上岸,水流速度是 1 米/秒,你现在有 M 点体力。
每消耗一点体力,你可以划一秒桨使船向上游前进 1 米,否则会向下游前进 1 米(水流),M 点体力需在救援队赶来前花光。
因为江面太宽了,凭借你自己的力量不可能上岸,请问,有多少种划桨的方案可以让你得救。
两个划桨方案不同是指:存在某一秒钟,一个方案划桨,另一个方案不划。
输入格式
输入一行包含三个整数 D, T, M。
输出格式
输出一个整数,表示可以让你得救的总方案数,答案可能很大,请输出方案数除以 1,000,000,007
的余数。
输入样例
1 6 3
输出样例
5
数据范围
对于 50% 的评测用例,
1
≤
T
≤
350
1≤T≤350
1≤T≤350
对于所有评测用例,
1
≤
T
≤
3000
,
1
≤
D
≤
T
,
1
≤
M
≤
1500
1≤T≤3000,1≤D≤T,1≤M≤1500
1≤T≤3000,1≤D≤T,1≤M≤1500
题解一(超时)
DFS:
#include <iostream>
using namespace std;
const int MOD = 1e9 + 7;
int ans;
int D, T, M;
void dfs(int T, int M, int D) // 距离救援还有 T 分钟,还剩 M 点体力,距离峡谷还有 D 米
{
if(!T)
{
if(!M) ans = (ans + 1) % MOD;
return;
}
if(M > 0) dfs(T - 1, M - 1, D + 1); // 消耗体力
if(D > 1) dfs(T - 1, M, D - 1); // 保留体力
}
int main()
{
cin >> D >> T >> M;
dfs(T, M, D);
cout << ans << endl;
return 0;
}
题解二
记忆化搜索:
#include <iostream>
#include <cstring>
using namespace std;
const int MOD = 1e9 + 7;
int ans;
int D, T, M;
int f[3010][1510];
int dfs(int T, int M, int D)
{
if(f[T][M] != -1) return f[T][M];
if(!T)
{
if(M) return 0;
return f[0][0] = 1;
}
f[T][M] = 0;
if(M > 0) f[T][M] = (f[T][M] + dfs(T - 1, M - 1, D + 1)) % MOD;
if(D > 1) f[T][M] = (f[T][M] + dfs(T - 1, M, D - 1)) % MOD;
return f[T][M];
}
int main()
{
memset(f, -1, sizeof f);
cin >> D >> T >> M;
cout << dfs(T, M, D) << endl;
return 0;
}