1. 程式人生 > >codeforces946D. Timetable(DP)

codeforces946D. Timetable(DP)

預處理一下每一天逃課i天能獲得的最大收益 我的預處理好蠢啊 但是不想改了 具體看醜醜的程式碼TATdp_i j表示第i天一共逃j節課所獲得的收益 類似揹包的轉移方程 dp[i][k + j] = max(dp[i][j + k], dp[i - 1][j] + cost[i][k]); // j為之前i - 1天逃課總數 第i天逃k節課最後再減去一下就行了寫了一晚上 寫崩了啊 我好菜
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
using namespace std;
char tu[505][505];
int tot[505];
int pre[505][505];
int cost[505][505];
int dp[505][505];

int main()
{
    memset(dp, 0, sizeof(dp));
    memset(cost, 0, sizeof(cost));
    int n, m, kk;
    scanf("%d%d%d", &n, &m, &kk);
    int ans = 0;
    for(int i = 1; i <= n; i++)
    {
        scanf("%s", tu[i] + 1);
        pre[i][0] = 0;
        for(int j = 1; j <= m; j++)
            pre[i][j] = pre[i][j - 1] + (tu[i][j] == '1');
        tot[i] = pre[i][m];

        int l, r;
        int summ = 0;
        for(int j = 1; j <= m; j++)
            if(tu[i][j] == '1')
            {
                l = j;
                break;
            }
        for(int j = m; j >= 1; j--)
            if(tu[i][j] == '1')
            {
                r = j;
                summ = r - l + 1;
                break;
            }
        ans += summ;
        for(int j = l; j <= r; j++)
            for(int k = j; k <= r; k++)
                cost[i][tot[i] - pre[i][k] + pre[i][j - 1]] = max(cost[i][tot[i] - pre[i][k] + pre[i][j - 1]], summ - (k - j + 1));
        cost[i][tot[i]] = summ;
    }

    int sub = 0;
    for(int i = 1; i <= tot[1]; i++) dp[1][i] = cost[1][i];
    int sum = tot[1];
    for(int i = 2; i <= n; i++)
    {
        sum += tot[i];
        for(int j = 0; j <= kk; j++)
            for(int k = 0; k + j <= kk; k++)
                dp[i][k + j] = max(dp[i][j + k], dp[i - 1][j] + cost[i][k]);
    }

    if(kk >= sum)
        puts("0");
    else
        printf("%d\n", ans - dp[n][kk]);
    return 0;
}