codeforces 946D
题意:
给
定
n
、
m
和
k
,
代
表
一
周
n
天
上
学
,
每
天
m
节
课
,
你
每
周
最
多
可
以
逃
课
k
节
。
给定n、m和k,代表一周n天上学,每天m节课,你每周最多可以逃课k节。
给定n、m和k,代表一周n天上学,每天m节课,你每周最多可以逃课k节。
给
定
n
行
m
列
,
第
i
行
第
j
列
为
0
(
代
表
无
课
)
或
1
(
代
表
有
课
)
。
给定n行m列,第i行第j列为0(代表无课)或1(代表有课)。
给定n行m列,第i行第j列为0(代表无课)或1(代表有课)。
每
天
的
在
校
时
间
为
第
一
节
课
到
最
后
一
节
课
间
隔
的
距
离
。
每天的在校时间为第一节课到最后一节课间隔的距离。
每天的在校时间为第一节课到最后一节课间隔的距离。
问
每
周
的
最
少
在
校
时
间
。
问每周的最少在校时间。
问每周的最少在校时间。
题解:
v
[
i
]
[
j
]
表
示
第
i
周
逃
第
j
节
课
换
取
的
自
由
时
间
,
将
问
题
转
化
为
分
组
背
包
。
v[i][j]表示第i周逃第j节课换取的自由时间,将问题转化为分组背包。
v[i][j]表示第i周逃第j节课换取的自由时间,将问题转化为分组背包。
d
p
[
j
]
表
示
每
周
逃
课
j
节
换
取
的
自
由
时
间
。
dp[j]表示每周逃课j节换取的自由时间。
dp[j]表示每周逃课j节换取的自由时间。
- 枚 举 每 天 的 最 小 在 校 时 间 , h o u r = m i n ( h o u r , c o u r s e [ r ] − c o u r s e [ l ] + 1 ) 枚举每天的最小在校时间,hour = min(hour, course[r]-course[l]+1) 枚举每天的最小在校时间,hour=min(hour,course[r]−course[l]+1)
- d p [ j ] = m a x ( d p [ j ] , d p [ j − k ] + v [ i ] [ k ] ) dp[j] = max(dp[j], dp[j-k]+v[i][k]) dp[j]=max(dp[j],dp[j−k]+v[i][k])
#include <bits\stdc++.h>
using namespace std;
const int N = 501;
int course[N], v[N][N];
int dp[N];
int main() {
int n, m, k;
cin >> n >> m >> k;
for(int i = 0 ; i < n ; i++){
string s;
cin >> s;
int pos = 0;
for(int j = 0 ; j < m ; j++){
if(s[j] == '1'){
pos++;
course[pos] = j;
}
}
for(int j = 0 ; j <= min(pos, k) ; j++){
int hour = 1 << 30;
for(int l = 1, r = pos-j ; r <= pos ; l++, r++){
hour = min(hour, course[r]-course[l]+1);
}
v[i][j] = m-(j == pos ? 0 : hour);
}
}
for(int i = 0 ; i < n ; i++){
for(int j = k ; j >= 0 ; j--){
for(int k = 0 ; k <= min(j, m) ; k++){
dp[j] = max(dp[j], dp[j-k]+v[i][k]);
}
}
}
cout << n*m-dp[k] << endl;
return 0;
}