zoukankan      html  css  js  c++  java
  • [SCOI2009]粉刷匠(动态规划,序列dp,背包)

    [SCOI2009]粉刷匠

    分别对每块木板做区间dp,设(g[i][j])表示前i个格子,刷恰好j次,并且第i格是合法的最多合法的格子数.从前往后枚举断点来转移就好了.

    这样处理再出来(g[i][j])每一块木板i刷j次的最大合法格子数.

    最后再合并每块木板的答案,用(dp[i][j])表示前i块木板,一共恰好刷了k次的最大合法格子数,用刷表法暴力背包合并就好了.

    很详细的注释.

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define maxn 55
    using namespace std;
    int n,m,T,ans,sum[maxn],dp[maxn][maxn*maxn];
    int f[maxn][maxn],g[maxn][maxn];
    char s[maxn];
    //分别对每块木板区间dp
    //再用背包来合并
    int main()
    {
    	cin>>n>>m>>T;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%s",s+1);
    		memset(g,0x8f,sizeof(g));
    		g[0][0]=0;
    		for(int j=1;j<=m;j++)sum[j]=sum[j-1]+(s[j]=='1');//蓝色的前缀和
    		//g[j][k]当前木板表示前j个格子,刷k次的最多合法的格子数,并且j是合法的格子
    		for(int j=1;j<=m;j++)
    			for(int k=1;k<=j;k++)
    				for(int l=0;l<j;l++)
    				{
    					if(s[j]=='1')g[j][k]=max(g[j][k],g[l][k-1]+sum[j]-sum[l]);
    					else g[j][k]=max(g[j][k],g[l][k-1]+j-l-sum[j]+sum[l]);
    				}
    		//f[j][k]表示第i块木板,恰好刷k次的最多合法格子数
    		for(int j=0;j<=m;j++)
    			for(int k=0;k<=j;k++)
    				f[i][k]=max(f[i][k],g[j][k]);
    	}
    	//dp[i][j]表示前i个块木板,恰好刷j次的最多的合法格子数
    	for(int i=1;i<=n;i++)
    		for(int j=0;j<=T&&j<=i*m-m;j++)
    			for(int k=0;k<=m;k++)
    				dp[i][j+k]=max(dp[i][j+k],dp[i-1][j]+f[i][k]);
    	for(int i=0;i<=T;i++)ans=max(ans,dp[n][i]);
    	cout<<ans<<endl;
    	return 0;
    }
    
    
  • 相关阅读:
    iscroll在iphone浏览器上闪动的BUG
    Emmet (ZenCoding) 缩写语法
    jqmobi快速开始(翻译)
    前端资源站点
    DOM Storage全解析
    html5离线应用
    XML的浏览器解析方案,正在尝试 。
    用 JavaScript来判断浏览器的种类
    delphi7判断字符串的组成
    没想到手机发邮件要占用那么大的空间
  • 原文地址:https://www.cnblogs.com/terribleterrible/p/9879111.html
Copyright © 2011-2022 走看看