codeforces946D. Timetable(DP)
阿新 • • 發佈:2018-12-24
預處理一下每一天逃課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; }