题意
传送门 NC 21675
题解
先考虑搜索,需要记录的变量有当前日期,工作总天数,已工作连续天数以及总花费的体力。显然体力的数据范围过大,考虑以前三个变量进行三维 D P DP DP。
d
p
[
i
]
[
j
]
[
k
]
dp[i][j][k]
dp[i][j][k] 代表当前日期为
i
i
i,总工作天数为
j
j
j,已连续工作
k
k
k 天时,花费的最小体力。非假期有选择工作与不工作两种选择,则有递推式
d
p
[
i
]
[
j
]
[
k
]
=
{
m
i
n
0
≤
k
≤
j
{
d
p
[
i
−
1
]
[
j
]
[
k
]
}
k
=
0
d
p
[
i
]
[
j
−
1
]
[
k
−
1
]
+
k
k
≥
1
a
n
d
s
[
i
]
=
′
1
′
i
n
f
o
t
h
e
r
w
i
s
e
dp[i][j][k]=\begin{cases} min_{0\leq k\leq j}\{dp[i-1][j][k]\} & k=0\\ dp[i][j-1][k-1]+k & k\geq 1 \ and\ s[i]='1'\\ inf & otherwise \\ \end{cases}
dp[i][j][k]=⎩⎪⎨⎪⎧min0≤k≤j{dp[i−1][j][k]}dp[i][j−1][k−1]+kinfk=0k≥1 and s[i]=′1′otherwise
#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define maxn 405
int n, k, dp[2][maxn][maxn];
char s[maxn];
int main()
{
scanf("%d%d", &n, &k);
scanf(" %s", s + 1);
int crt = 0, nxt = 1;
memset(dp[crt], 0x3f, sizeof(dp[crt]));
dp[crt][0][0] = 0;
for (int i = 1; i <= n; i++)
{
memset(dp[nxt], 0x3f, sizeof(dp[nxt]));
for (int j = 0; j < i; j++)
{
int res = inf;
for (int k = 0; k <= j; k++)
{
res = min(res, dp[crt][j][k]);
}
dp[nxt][j][0] = res;
}
if (s[i] == '1')
{
for (int j = 1; j <= i; j++)
{
for (int k = 1; k <= j; k++)
{
dp[nxt][j][k] = dp[crt][j - 1][k - 1] + k;
}
}
}
swap(crt, nxt);
}
bool f = 0;
int res = 0;
for (int i = n; !f && i >= 0; i--)
{
for (int j = n; j >= 0; j--)
{
if (dp[crt][i][j] <= k)
{
res = i, f = 1;
break;
}
}
}
printf("%d\n", res);
return 0;
}