题意:一个星期有n天,每天m小时,一小时一节课,每天一个01字符串0代表没课,1代表有课,一个星期可以翘k节课,一天在学校的时间为你去上的第一节课到最后一节课,问你一个星期最少的在学校待的时间。
思路:对于每天,暴力出数组t,t[i]=x代表该天上i小时课最少x小时在学校。就可以dp出dp数组。dp[i]=x代表这个星期上i节课最少多少小时在学校。
转移方程 dp[i] = min(dp[i],dp[i-j]+t[j]);
注意 i从sum到sum-k;(sum为当前天时,一共能上的课) j从0到min(len,i) (len为今天能上的课);不然会超时!!
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e3+50;
int pos[505],t[505];
int dp[250050];
int main()
{
// freopen("in.txt", "r", stdin);
ios::sync_with_stdio(false);
int n,m,kk;
cin>>n>>m>>kk;
string str;
int sum = 0;
memset(dp,0x3f,sizeof(dp));
dp[0] = 0;
for(int i = 1; i<=n; i++)
{
cin>>str;
int len = 0;
for(int j = 0; j<m; j++)
if(str[j]=='1')
pos[len++] = j;
sum+=len;
memset(t,0x3f3f3f3f,sizeof(t));//上t节课最少的在校时间
t[0] = 0;
if(len) t[1] = 1;
for(int j = 0; j<len-1; j++)
for(int k = j+1; k<len; k++)
t[k-j+1] = min(t[k-j+1],pos[k]-pos[j]+1);
for(int k = sum; k>=sum-kk; k--)
for(int j = 0; j<=min(len,k); j++)
dp[k] = min(dp[k],dp[k-j]+t[j]);
}
cout<<dp[sum-kk]<<endl;
return 0;
}