• BZOJ1296: [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 3
    111111
    000000
    001100

    Sample Output

    16

    HINT 

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

    Solution

    啊..感觉这个dp不难推啊。。就是推不出来

    设$f[i][j]$表示前i条刷j次能刷对的格子数

    $g[i][j][k]$表示第i行刷了j次前k个能刷的最大格子数 

    先把g算出来,然后用来转移$f[i][j]$

    g的转移:

    c数组为前缀和,c[i][j]表示第i行1~j的前缀和(这里用来处理两种颜色)

    $$g[i][j][k]=max(g[i][j][k],g[i][j-1][l]+max(c[i][k]-c[i][l],k-l-c[i][k]+c[i][l]))$$

    就是找个转移点然后涂蓝色还是涂红色取个max这样,效率$O(n^4)$

    f的转移:

    $$f[i][j]=max(f[i][j],f[i-1][j-k]+g[i][k][m])$$

    有了g这个就很好推了

    我就没有想到用个g来优化转移,死活想不出来

    答案就扫一遍求个max就好

    总复杂度是$O(n^4+n^2t)$

    #include <bits/stdc++.h>
    
    using namespace std ;
    
    #define N 2510
    
    int a[ 60 ][ 60 ] , c[ 60 ][ 60 ] ;
    int n , m , t ;
    int f[ 60 ][ N ] ;
    //前i条刷j次能刷对的格子数
    int g[ 60 ][ 60 ][ 60 ] ; 
    //第i行刷了j次前k个能刷的最大格子数 
    
    int main() {
        scanf( "%d%d%d" , &n , &m , &t ) ;
        for( int i = 1 ; i <= n ; i ++ ) {
            char ch[ 100 ] ;
            scanf( "%s" , ch+1 ) ;
            for( int j = 1 ; j <= m ; j ++ ) {
                c[ i ][ j ] = c[ i ][ j - 1 ] + ( ch[ j ] ^ '0' ) ;
            }
        }
        for( int i = 1 ; i <= n ; i ++ ) {
            for( int j = 1 ; j <= m ; j ++ ) {
                for( int k = 1 ; k <= m ; k ++ ) {
                    for( int l = j - 1 ; l < k ; l ++ ) {
                        g[i][j][k]=max(g[i][j][k],g[i][j-1][l]+max(c[i][k]-c[i][l],k-l-c[i][k]+c[i][l]));
                    }
                }
            }
        }
        for( int i = 1 ; i <= n ; i ++ ) {
            for( int j = 1 ; j <= t ; j ++ ) {
                for( int k = 0 ; k <= min( j , m ) ; k ++ ) {
                    f[ i ][ j ] = max( f[ i ][ j ] , f[ i - 1 ][ j - k ] + g[ i ][ k ][ m ] ) ;
                }
            }
        }
        int ans = 0 ;
        for( int i = 1 ; i <= t ; i ++ ) ans = max( ans , f[ n ][ i ] ) ;
        printf( "%d
    " , ans ) ;
        return 0 ;
    }
  • 相关阅读:
    http://www.kankanews.com/ICkengine/archives/18078.shtml
    c# ArrayList 的排序问题!
    MVC各种传值方式
    MVC3学习第五章 排山倒海第一变母版页,模型
    MVC3学习第三章 剑出鞘之前奏控制器,URL路由
    MVC3学习第二章 剑出鞘之看剑vs2010安装MVC3和建立你的第一个MVC3项目
    MVC3学习第四章 剑出鞘之后续MVC3的新特性之Razor视图解析
    MVC3学习第一章 掀起它的盖头来
    有关匿名函数执行与传参
    ubuntu12.04安装jdk7u79linuxi586.tar.gz
  • 原文地址:https://www.cnblogs.com/henry-1202/p/9853480.html
Copyright © 2020-2023  润新知