SCOI2009粉刷匠
Description
windy有 N 条木板需要被粉刷。 每条木板被分为 M 个格子。 每个格子要被刷成红色或蓝色。 windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色。 每个格子最多只能被粉刷一次。 如果windy只能粉刷 T 次,他最多能正确粉刷多少格子? 一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷。
Input
输入文件paint.in第一行包含三个整数,N M T。 接下来有N行,每行一个长度为M的字符串,'0'表示红色,'1'表示蓝色。
Output
输出文件paint.out包含一个整数,最多能正确粉刷的格子数。
Solution
首先动规产生每块木板前几笔最多能正确粉刷多少个格子。再一次动规产生前几块木板刷几笔最多能正确粉刷多少格子,所以需要两次动规。
Code
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 using namespace std; 5 int tot[111],f[111][111],w[111][111],f2[111][3000]; 6 char a[111][111]; 7 int main() 8 { 9 int n,m,t; 10 cin>>n>>m>>t; 11 for (int i=1; i<=n; i++) 12 for (int j=1; j<=m; j++) 13 cin>>a[i][j]; 14 int sum; 15 for (int k=1; k<=n; k++) 16 { 17 for (int i=1; i<=m; i++) 18 if (a[k][i]=='0') tot[i]=tot[i-1]+1; 19 else tot[i]=tot[i-1]; 20 for (int i=1; i<=m; i++) 21 for (int j=1; j<=m; j++) 22 { 23 f[j][i]=0; 24 for (int p=0; p<=j-1; p++) 25 { 26 sum=tot[j]-tot[p]; 27 f[j][i]=max(f[j][i],f[p][i-1]+max(j-sum-p,sum)); 28 } 29 for (int i=1;i<=m;i++) 30 w[k][i]=f[m][i];//w表示第k块木板涂i笔,f表示这块木板前m个格子(即整块)涂i笔 31 } 32 } 33 for (int i=1;i<=n;i++) 34 for (int j=1;j<=t;j++) 35 for (int k=1;k<=j;k++) 36 if (k<=m) f2[i][j]=max(f2[i-1][j-k]+w[i][k],f2[i][j]); 37 cout<<f2[n][t]<<endl; 38 return 0; 39 }
Source
http://www.lydsy.com/JudgeOnline/problem.php?id=1296