Codeforces 946D - Timetable

21 篇文章 0 订阅
16 篇文章 0 订阅

链接:http://codeforces.com/problemset/problem/946/D

题意:有n天,每天m节课,总共可以逃k节课,问怎么逃课能使上课时间最短,并输出。

思路:按多重背包的思路来考虑,dp[i][j]表示,对于前i天如果第i天逃j节课能少上的时间是多少。

vv[i][j]代表对于第i天,如果逃j节课最多能少上的时间。

sum[i]代表第i天不逃课要上的时间,z是第i天如果逃z节课。

转移方程:dp[i][j]=max(dp[i][j],dp[i-1][j-z]+vv[i][z]);


代码:

#include<bits/stdc++.h>
using namespace std;

char s[505][505];
int v[505];
int sum[505];
int vv[505][505];
int dp[505][505];

int main()
{
    int n,m,k;
    int cnt=0;
    int sum_time=0;
    memset(sum,0,sizeof(sum));
    scanf("%d%d%d",&n,&m,&k);
    memset(vv,0,sizeof(vv));
    for(int i=0;i<n;i++)
    {
        scanf("%s",s[i]);
        int cnt=0;
        memset(v,0,sizeof(v));
        for(int j=0;j<m;j++)
        {
            if(s[i][j]=='1') v[cnt++]=j;
        }
        sum[i]=cnt;
        if(!cnt) continue;
        sum_time+=(v[cnt-1]-v[0]+1);

        for(int j=1;j<=k;j++)  //v[i][j] 第i行逃j门课时减少的时间
        {
             if(j>=cnt) {
                vv[i][j]=v[cnt-1]-v[0]+1;continue;
             }
              int left=cnt-j;
              int all=v[cnt-1]-v[0]+1;
              if(left==0) {vv[i][j]=all;continue;}
              for(int z=0;z+left<=cnt;z++)
              {
                 vv[i][j]=max(vv[i][j],v[z]-v[0]+v[cnt-1]-v[z+left-1]);
              }
         }
    }

//    for(int i=0;i<n;i++)
//    {
//        for(int j=0;j<m;j++)
//        {
//            printf(j==m-1?"%d\n":"%d ",vv[i][j]);
//        }
//    }

    memset(dp,0,sizeof(dp));

    for(int i=0;i<=k;i++) {dp[0][i]=vv[0][i];}

    for(int i=1;i<n;i++)   //前i天
    {
        for(int j=k;j>=0;j--)  //逃j节课
        {
            for(int z=0;z<=j&&z<=sum[i];z++) //假设第i天如果逃z节课
            {
                dp[i][j]=max(dp[i][j],dp[i-1][j-z]+vv[i][z]);
            }
        }
    }
    cout<<sum_time-dp[n-1][k]<<endl;

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值