SCOI2009粉刷匠

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

以上是关于SCOI2009粉刷匠的主要内容,如果未能解决你的问题,请参考以下文章

SCOI2009粉刷匠

bzoj1296SCOI2009粉刷匠

BZOJ 1296: [SCOI2009]粉刷匠

1296: [SCOI2009]粉刷匠[多重dp]

[SCOI2009]粉刷匠(分组背包)

[SCOI2009]粉刷匠(分组背包)