1. 程式人生 > >【codeforces 946D】Timetable(預處理+分組揹包)

【codeforces 946D】Timetable(預處理+分組揹包)

    =-=以前揹包沒學好。。。居然是第一次做分組揹包的題,咳咳    不過這題比較厲害的是它的預處理。。。心態崩了,為什麼有的時候一個回車會往下走這麼多行想刪回車,一下子就刪了一段,還不知道在哪撤回mmp,就寫一丟丟列舉左右端點可以一起移動要令value[i][num[i]]=m然後揹包的第二個迴圈是從大到小,不然就相當於在這一類物品中拿了多個東西程式碼程式碼。。。生氣
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
const int inf=999999999;
int dp[600],num[600],fin[600][600],value[600][600];
int main()
{
    int n,m,v;
    while(~scanf("%d%d%d",&n,&m,&v))
    {
        for(int i=1;i<=n;i++)//輸入
        {
            int t=0;
            for(int j=1;j<=m;j++)
            {
                //printf("test\n");
                char a;
                scanf(" %c",&a);
                if(a=='1')fin[i][++t]=j;//fin[i][j]存第i天第j節課在第幾節
            }
            num[i]=t;//num[i]儲存第i天課的數量
        }
        for(int i=1;i<=n;i++)//計算value,即第i天翹n節課節約的最大時間
        {
            for(int j=0;j<=min(num[i],v);j++)
            {
                int res=inf;
                int p,q;
                for(int k=0;k<=j;k++)
                {
                    p=k;q=j-k;//列舉左右端點,即左縮排p位右縮排q位
                    res=min(res,fin[i][num[i]-q]-fin[i][p+1]+1);
                }
                value[i][j]=m-res;
                //printf("%d\n",value[i][j]);
            }
            value[i][num[i]]=m;
        }
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)//揹包部分
        {
            for(int j=v;j>=0;j--)
            {
                //printf("%
[email protected]
\n",j); for(int k=0;k<=min(num[i],j);k++) { dp[j]=max(dp[j],dp[j-k]+value[i][k]);//dp[i]為翹i節課能節約的最大時間 }//printf("%d\n",dp[j]); } } printf("%d\n",n*m-dp[v]); } return 0; }
=-=