zoukankan      html  css  js  c++  java
  • 1296: [SCOI2009]粉刷匠

    Description

    windy有 N 条木板需要被粉刷。 每条木板被分为 M 个格子。 每个格子要被刷成红色或蓝色。 windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色。 每个格子最多只能被粉刷一次。 如果windy只能粉刷 T 次,他最多能正确粉刷多少格子? 一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷。

    Input

    输入文件paint.in第一行包含三个整数,N M T。 接下来有N行,每行一个长度为M的字符串,'0'表示红色,'1'表示蓝色。

    Output

    输出文件paint.out包含一个整数,最多能正确粉刷的格子数。

    Sample Input

    3 6 3
    111111
    000000
    001100

    Sample Output

    16

    HINT

    30%的数据,满足 1 <= N,M <= 10 ; 0 <= T <= 100 。 100%的数据,满足 1 <= N,M <= 50 ; 0 <= T <= 2500 。

    题解:我觉得这道题的思路还是比较好想的,但是具体落实我自己却不大会,只能。。。
    思路是先提前处理好每块木板涂几次时最多能涂几个格子,然后再去讨论前几块木板涂几笔时,所能涂最多的格子,最后前n块木板涂m笔便是答案。
    所以这题有两个动归,具体看程序后的注释,会详细解释。
    动态转移方程:具体程序看!
    #include<iostream>
    #include<cstdio>
    #include<string>
    using namespace std;
    int n,m,t,sum,f[100][100],f2[100][3000],tot[100],w[100][100];
    char a[100][100],ch;
    int max(int a,int b)
    {
        if (a>b) return a;
        return b;
    }
    int main()
    {
      cin>>n>>m>>t;
      for (int i=1;i<=n;i++)
      for (int j=1;j<=m;j++)
      {
       cin>>ch;//输入
       a[i][j]=ch;
       }
      for (int k=1;k<=n;k++)//开始一块一块木板处理
      {
          tot[0]=0;
          for (int i=1;i<=m;i++) if (a[k][i]=='0') tot[i]=tot[i-1]+1;
           //记录这块木板前i个格子中有几个格子为0(即红色)
          else tot[i]=tot[i-1];
          for (int i=1;i<=m;i++)
           for (int j=1;j<=m;j++)//f[j][i]表示前j格子涂i笔所能涂的最多格子。//这里要注意要后枚举格子数即j需为格子数。
           {
               f[j][i]=0;
            for (int p=0;p<=j-1;p++)//枚举上一笔的结束处
            {
                sum=tot[j]-tot[p];//p+1——j个格子中为‘0’的个数
                f[j][i]=max(f[j][i],f[p][i-1]+max(j-sum-p,sum));
                   //f[p][i-1]指前p个格子涂i-1笔能涂得最多格子数,
                   //max(j-sum-p,sum)指选择p+1——j这段区间内涂'0'或涂‘1’所能达到的最优值.
          }
        for (int i=1;i<=m;i++)
        w[k][i]=f[m][i];//w[k][i]和f[m][i]都指这块木板涂i笔时所能涂对的格子数。
      }
      for (int i=1;i<=n;i++)//前i块木板
       for (int j=1;j<=t;j++)//涂几笔
        for (int k=1;k<=j;k++)//第i块木板涂k笔
        if (k<=m) f2[i][j]=max(f2[i-1][j-k]+w[i][k],f2[i][j]);
      cout<<f2[n][t]<<endl;
      return 0;
    }
     
  • 相关阅读:
    C#_数据访问类查询 和 属性扩展
    C#_0913 完整修改删除、实体类和数据访问类
    webform基础
    TreeView, 数据导出
    无边框窗体,tiner控件
    容器,打印设置
    多窗体,菜单工具栏
    公共控件
    winform
    数据访问类查询
  • 原文地址:https://www.cnblogs.com/2014nhc/p/6231190.html
Copyright © 2011-2022 走看看