bzoj1296【SCOI2009】粉刷匠
阿新 • • 發佈:2017-08-11
margin 我們 紅色 sample rgb math mon 20px ans
Submit: 1479 Solved: 837
[
111111
000000
001100
1296: [SCOI2009]粉刷匠
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1479 Solved: 837
[
id=1296" style="color:blue; text-decoration:none">Submit][Status][Discuss]
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 。
Source
這道題做法是兩次DP。
能夠發現不同的木板是相互獨立,互相無影響的。
所以我們能夠O(n^3)暴力DP計算出每一條木板,粉刷j次最多能正確粉刷的數量。
然後對於不同的木板再用一次DP計算答案。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long using namespace std; int n,m,t,ans=0; int sum[55],f[55][55],g[55][2505]; char s[55]; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int main() { n=read();m=read();t=read(); F(i,1,n) { scanf("%s",s+1); F(j,1,m) sum[j]=sum[j-1]+(s[j]=='1'); F(k,1,m) F(j,1,m) { f[j][k]=0; F(l,0,j-1) { int tmp=sum[j]-sum[l]; f[j][k]=max(f[j][k],f[l][k-1]+max(tmp,j-l-tmp)); } } F(j,1,t) F(k,1,min(j,m)) g[i][j]=max(g[i][j],g[i-1][j-k]+f[m][k]); } F(i,1,t) ans=max(ans,g[n][i]); printf("%d\n",ans); return 0; }
bzoj1296【SCOI2009】粉刷匠