时/空限制:1s / 64MB
题解(记忆化搜索):
- 注意下标i只需要定义一次
- 必须记忆化,否则会超时
- 记忆化需要初始化为-1,然后进入dfs后再定义为正无穷
#include <iostream>
#include <cstring>
using namespace std;
const int N = 400;
int n;
int a[N], b[5];
int memo[N];
int dfs(int u) {
if (memo[u] != -1) return memo[u];
if (u > n) return 0;
memo[u] = 1e9 + 10;
int i = u + 1;
memo[u] = min(memo[u], b[1] + dfs(i));
while (i <= n && a[i] < a[u] + 7) ++ i;
memo[u] = min(memo[u], b[2] + dfs(i));
while (i <= n && a[i] < a[u] + 30) ++ i;
memo[u] = min(memo[u], b[3] + dfs(i));
return memo[u];
}
int main() {
memset(memo, -1, sizeof memo);
cin >> n;
for (int i = 1; i <= n; ++ i) {
cin >> a[i];
}
for (int i = 1; i <= 3; ++ i) {
cin >> b[i];
}
cout << dfs(1);
}
题解(线性dp):
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 375;
int days[N], f[N], costs[4];
int get(int i, int cnt)
{
int day = i;
while (day >= 1 && days[day] >= days[i] - cnt + 1) day -- ;
return day;
}
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; i ++ ) cin >> days[i];
for (int i = 1; i <= 3; i ++ ) cin >> costs[i];
for (int i = 1; i <= n; i ++ )
{
f[i] = f[i - 1] + costs[1];
f[i] = min(f[i], f[get(i, 7)] + costs[2]);
f[i] = min(f[i], f[get(i, 30)] + costs[3]);
}
cout << f[n] << endl;
return 0;
}