这题由于前一个小时会对后一个小时造成影响,所以必须考虑0时是否连续问题。可以在dp时分别令0时为连续与不连续,目标状态就取第n时休息的状态和不休息的状态。
这题必须开滚动数组,否则空间会爆。
using namespace std;
// #define int long long
#define INF 1e18
#define endl '\n'int n, b;
int arr[4003];int f[2][3833][2] = {0};
void init()
{
}
void solve()
{memset(f, -0x3f, sizeof(f));cin >> n >> b;f[1][0][0] = 0;f[1][1][1] = 0;for (int i = 1; i <= n; i++){cin >> arr[i];}for (int i = 2; i <= n; i++){for (int j = 0; j <= b; j++){int nowi = i & 1;f[nowi][j][0] = max({f[nowi ^ 1][j][1], f[nowi ^ 1][j][0]});if (j >= 1){f[nowi][j][1] = max({f[nowi ^ 1][j - 1][0], f[nowi ^ 1][j - 1][1] + arr[i]});}}}int ans1 = max(f[n & 1][b][0], f[n & 1][b][1]);memset(f, -0x3f, sizeof(f));f[1][0][0] = 0;f[1][1][1] = arr[1];for (int i = 2; i <= n; i++){for (int j = 0; j <= b; j++){int nowi = i & 1;f[nowi][j][0] = max({f[nowi ^ 1][j][1], f[nowi ^ 1][j][0]});if (j >= 1){f[nowi][j][1] = max({f[nowi ^ 1][j - 1][0], f[nowi ^ 1][j - 1][1] + arr[i]});}}}int ans2 = f[n & 1][b][1];cout << max(ans1, ans2) << endl;
}signed main()
{
#ifdef LOCAL_ENVfreopen("input.txt", "r", stdin);freopen("output.txt", "w", stdout);
#endifios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);ios::sync_with_stdio(false), cin.tie(0);int T = 1;// cin >> T;for (int i = 1; i <= T; i++){solve();}return 0;
}
收获:
1.环形问题不仅有破环成链一个思路,还可以处理环形边界,令环形边界为连续和不连续两种状态,并分别计算。