题目链接:https://cometoj.com/contest/67/problem/B?problem_id=3796
反思:
当时没什么思路,最后想了一个建图求最长路的方法,来不及写了,这次写的是题解的dp方法,图论的有时间会尝试。
思路:
从第二天开始计算,对每一天都跑一次完全背包,在跑背包之前先处理一下上一天收益造成的变化即dp[ i ][ j + f [ j ] ] = max(dp[ i ] [ j ] , f[ i ] [ j + f [ j ] ] ),之后完全背包的转移方程为dp[ i ] [ j ] = max( dp[ i ] [ j + a[ i ] ] + b [ i ] , dp[ i ] [ j ] ).
注意:还没有转移到的状态为无效状态 , 需要置为很小的负数.
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3005;
int f[maxn] , dp[maxn][maxn];
int a[maxn] , b[maxn];
int main() {
int n , m , k;
ios::sync_with_stdio(0);
cin >> n >> m >> k;
int tmp = 0;
for(int i = 0 ; i <= k ; i++) {
cin >> f[i];
tmp = max(f[i] + i , tmp);
}
for(int i = 0 ; i < m ; i++) {
cin >> a[i] >> b[i];
}
memset(dp , 128 , sizeof(dp));
dp[1][0] = 0;
for(int p = 2 ; p <= n ; p++) {
for(int j = 0 ; j <= k ; j++) {
dp[p][j + f[j]] = dp[p - 1][j];
}
for(int i = 0 ; i < m ; i++) {
for(int j = tmp - a[i]; j >= 0 ; j--) {
dp[p][j] = max(dp[p][j + a[i]] + b[i] , dp[p][j]);
}
}
}
int ans = 0 ;
for(int i = 0 ; i <= tmp ; i++)ans = max(ans , dp[n][i] + i + f[i]);
cout << ans << "\n";
return 0;
}