您的位置:首页 > 其它

codeforces_946D_Timetable(分组背包)

2018-03-08 23:03 357 查看
传送门

题意:有长度为m的字符串n个,代表n天的课表,1表示这个时间要上课,0表示不要上课,一天在学校时间为第一个1到最后一个1的时间。然后,可以逃k次课,求在学校的最少时间。

思路:预处理出g[i][k]表示第i天逃k节课呆在学校的最少时间。预处理中记录每天1的个数,然后和1出现的下表,然后枚举长度1,取一手最小值。接下来分组背包。

#include<bits/stdc++.h>
#define debug(a) cout << #a << " " << a << endl
#define LL long long
#define PI acos(-1.0)
#define eps 1e-6
const int N=500+7;
int g

;
int dp

;
char str
;
using namespace std;
init()
{
for(int i=0;i<507;i++)
for(int j=0;j<507;j++)
dp[i][j]=1e9;
}
int main ()
{
//yyy_3y
//freopen("1.in","r",stdin);
int n,m,lim; scanf("%d%d%d",&n,&m,&lim);
for(int i=1;i<=n;i++){
scanf("%s",str+1);
init();
vector<int> stk;
int cnt=0;
for(int j=1;j<=m;j++){
if(str[j]=='1'){
cnt++;
stk.push_back(j);
}
}

for(int j=0;j<=lim;j++){
if(cnt<=j) g[i][j]=0;
else {
g[i][j]=m;
for(int k=0;k+(cnt-j-1) < cnt;k++){
g[i][j]=min(g[i][j],stk[k+cnt-j-1]-stk[k]+1);
}
}
//        printf("%d %d %d\n",i,j,g[i][j]);
}
}
for(int j=0;j<=lim;j++) dp[1][j]=g[1][j];
for(int i=2;i<=n;i++){
for(int j=lim;j>=0;j--){
for(int k=0;k<=j;k++){
dp[i][j]=min(dp[i][j],dp[i-1][j-k]+g[i][k]);
}
}
}
printf("%d\n",dp
[lim]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  分组背包