- 题目链接:http://codeforces.com/contest/946/problem/D
- 题意:设一个星期有n天,每天有m小时,给你n个长为m的字符串(由0、1组成),1表示要上课的时段。你每天需要花在学校的时间是从第一个1到最后一个1(包括头尾)。你可以翘掉最多k节课,求你一个n天总计待在学校的最小时间
- 算法:dp
- 思路:
- 遍历每天
- 用mn[i]记录当天,要上连续的i节课后所需花费的最小时间。
- 设当天总共有len天,则 mn[len-1] 必然从 mn[len] 中取,同理 mn[len-2] 必从 mn[len-1] 中取
- dp[i][j] 表示在前i天总共翘掉j(j不一定等于k,因为不一定需要在前i天翘完所有k节课)节课所需花的最小时间,设 第 i 天总共要翘掉x节课,则状态转移方程为
- dp[i][j] = min(d[i][j], d[i-1][j-x] + mn[len-x])
- 即在前i天翘掉总共j节课后所需花费的最小时间 = min(花费时间的最大值(即i*m),前i-1天翘掉总共j-x节课后所需花费的最小时间 + 当天上len-x节课所需花费的最小时间 )
#include <bits/stdc++.h>
#define pi acos(-1)
#define fastcin ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const LL ll_INF = 0x3f3f3f3f3f3f3f3f;
const int maxn =500 + 10;
const LL mod = 1e9+7;
string s;
int loc[maxn], mn[maxn], dp[maxn][maxn];
int main()
{
fastcin;
int n, m, k;
cin >> n >> m >> k;
for(int i=1; i<=n; i++){
cin >> s;
int len=0;
for(int j=0; j<s.size(); j++){
if(s[j]=='1') loc[++len]=j;
}
for(int l=1; l<=len; l++){
mn[l]=m;
for(int j=1; j<=len-l+1; j++){
mn[l]=min(mn[l], loc[j+l-1]-loc[j]+1);
}
}
for(int j=0; j<=k; j++){
int l;
for(l=min(len, j), dp[i][j]=i*m; l>=0; l--){
dp[i][j] = min(dp[i][j], dp[i-1][j-l]+mn[len-l]);
}
}
}
cout << dp[n][k] << endl;
}