《算法进阶指南》环形结构上的DP问题 休息时间
这题由于前一个小时会对后一个小时造成影响,所以必须考虑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_ENV
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
ios_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.环形问题不仅有破环成链一个思路,还可以处理环形边界,令环形边界为连续和不连续两种状态,并分别计算。

浙公网安备 33010602011771号