zoukankan      html  css  js  c++  java
  • code1744 方格染色

    稍微复杂一点的划分dp

    设f[i][j][k]为第i行前j个k次粉刷正确的最大值

    由于每行循环使用,可以去掉第一维,但每次不要忘了清零(卡了好久)

    f[j][k]=max{ f[u][j-1] + max(u+1到j的蓝色的个数,u+1到j的红颜色的个数) }

    设h[i][k]为第i行分成k份的最大值

    h[i][k]=f[i][m][k]

    设dp[i][k]为前i行总共分成k份的最大值

    dp[i][k]=dp[i-1][t-x]+h[i][x]

    x表示在第i行使用x次

    代码如下:

    #include<iostream>
    #define Size 55
    #define Max_t 3000 
    using namespace std;
     
    char a[Size][Size];
    int f[Size][Size];
    int h[Size][Size];
    int dp[Size][Max_t];
    int s1[Size][Size],s2[Size][Size];
    int n,m,t;
    
    inline int sum1(int i,int l,int r){return s1[i][r]-s1[i][l-1];}
    inline int sum2(int i,int l,int r){return s2[i][r]-s2[i][l-1];}
    
    int main(){
        freopen("1744.in","r",stdin);
        
        cin>>n>>m>>t;
        for(int i=1;i<=n;i++){
            cin>>a[i]+1;
            for(int j=1;j<=m;j++){
                s1[i][j]=s1[i][j-1];
                s2[i][j]=s2[i][j-1];            
                if(a[i][j]=='1')s1[i][j]++;
                else s2[i][j]++;
            }
        }
        
        //test
        /*
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                cout<<s1[i][j]<<' ';
            }
            cout<<endl;
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                cout<<s2[i][j]<<' ';
            }
            cout<<endl;
        }
        */
        
        for(int i=1;i<=n;i++){//
            for(int j=1;j<=m;j++){//前j个数 
                for(int k=1;k<=min(t,j);k++){//分成k份 
                    f[j][k]=0;//注意f是每行重复使用的,需要清零! 
                    for(int u=k-1;u<=j-1;u++){//分割点 
                        f[j][k]=max(f[j][k], f[u][k-1]+max(sum1(i,u+1,j),sum2(i,u+1,j)));
                    }
                    //cout<<i<<','<<j<<','<<k<<':'<<f[j][k]<<endl; 
                }
            }
            //cout<<"----------"<<endl;
            for(int k=1;k<=min(m,t);k++){
                h[i][k]=f[m][k];
                //cout<<i<<','<<k<<':'<<h[i][k]<<endl; 
            }
            //cout<<"------------------------------"<<endl;
        }
        
        for(int i=1;i<=n;i++){
            for(int k=1;k<=t;k++){
                for(int x=0;x<=k;x++){
                    dp[i][k]=max(dp[i][k], dp[i-1][k-x]+h[i][x]);    
                }
            }
        }
        
        cout<<dp[n][t]<<endl;
        
        fclose(stdin);
        return 0;
    }

    再次提醒自己注意f重用的清零!

  • 相关阅读:
    视频:JDBCRDD源码及自定义JDBCRDD的分区策略
    聊聊spark-submit的几个有用选项
    线性求第k大
    汇编基础 第一章_总线
    长度不超过n的连续最大和___优先队列
    ISAP
    次小生成树
    k短路
    求出欧拉回路,欧拉路径
    拓扑排序bfs_dfs
  • 原文地址:https://www.cnblogs.com/FuTaimeng/p/5440841.html
Copyright © 2011-2022 走看看