BZOJ_1296_[SCOI2009]粉刷匠_DP
阿新 • • 發佈:2018-07-08
整數 int scanf pac esc sample 一行 \n algo
111111
000000
001100
BZOJ_1296_[SCOI2009]粉刷匠_DP
Description
windy有 N 條木板需要被粉刷。 每條木板被分為 M 個格子。 每個格子要被刷成紅色或藍色。 windy每次粉刷,只能選擇一條木板上一段連續的格子,然後塗上一種顏色。 每個格子最多只能被粉刷一次。 如果windy只能粉刷 T 次,他最多能正確粉刷多少格子? 一個格子如果未被粉刷或者被粉刷錯顏色,就算錯誤粉刷。
Input
輸入文件paint.in第一行包含三個整數,N M T。 接下來有N行,每行一個長度為M的字符串,‘0‘表示紅色,‘1‘表示藍色。
Output
輸出文件paint.out包含一個整數,最多能正確粉刷的格子數。
Sample Input
3 6 3111111
000000
001100
Sample Output
16HINT
30%的數據,滿足 1 <= N,M <= 10 ; 0 <= T <= 100 。 100%的數據,滿足 1 <= N,M <= 50 ; 0 <= T <= 2500 。
由於每行之間是獨立的,可以分別對每行DP。
設h[i][j]表示前i個位置塗了j次。
然後放在一起,用每行使用塗的次數來轉移。
代碼:
#include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> using namespace std; int h[55][55],g[55][55],f[55][2550],n,m,K,s1[55],s2[55]; char s[55]; int main() { scanf("%d%d%d",&n,&m,&K); int i,j,k,l; for(i=1;i<=n;i++) { scanf("%s",s+1); for(j=1;j<=m;j++) s1[j]=s1[j-1]+(s[j]==‘1‘),s2[j]=s2[j-1]+(s[j]==‘0‘); memset(h,0,sizeof(h)); for(j=1;j<=m;j++) { for(k=1;k<=j;k++) { h[j][k]=h[j-1][k]; for(l=0;l<j;l++) { h[j][k]=max(h[j][k],h[l][k-1]+max(s1[j]-s1[l],s2[j]-s2[l])); } } } for(j=1;j<=m;j++) g[i][j]=h[m][j]; } int ans=0; for(i=1;i<=n;i++) { for(j=0;j<=K;j++) { for(k=0;k<=j;k++) { f[i][j]=max(f[i][j],f[i-1][k]+g[i][j-k]); } ans=max(ans,f[i][j]); } } printf("%d\n",ans); }
BZOJ_1296_[SCOI2009]粉刷匠_DP