思路:
dp[i][j][k] 表示对于前i天一共工作了j天现在连续工作了k天的最小花费 滚动数组优化掉第一维(不然会MLE)
if(s[i]=='0') 为0只能休息
dp[j][0]=min(dp[j][0],dp[j][k])
if(s[i]=='1')
dp[j][0]=min(dp[j][0],dp[j][k]) 选择休息
dp[j][k]=min(dp[j][k],dp[j-1][k-1]+k) 选择工作
然后发现s[i]==1 选择休息和s[i]==0的转移方程一样
所以
dp[j][0]=min(dp[j][0],dp[j][k]) &&
if(s[i]=='1') dp[j][k]=min(dp[j][k],dp[j-1][k-1]+k)
对于总共工作了j天 j这一层的循环需要倒序
因为是要么做 要么不做 效仿01背包 不然同一天可能会重复计算 最后要找的答案即最小花费≤k的最大的j即可
#include<bits/stdc++.h>
using namespace std;
int dp[505][505];
char s[505];
int main()
{
int n,k;
cin>>n>>k;
cin>>s+1;
memset(dp,0x3f,sizeof dp);
dp[0][0]=0;
for(int i=1;i<=n;i++){
for(int j=i;j;j--){
for(int k=1;k<=j;k++){
dp[j][0]=min(dp[j][0],dp[j][k]);///选择休息
if(s[i]=='1')
dp[j][k]=min(dp[j][k],dp[j-1][k-1]+k);///选择工作
}
}
}
for(int i=n;i>=0;i--){
for(int j=0;j<=i;j++){
if(dp[i][j]<=k){
cout<<i<<endl;
return 0;
}
}
}
}
京公网安备 11010502036488号