码迷,mamicode.com
首页 > 其他好文 > 详细

【Luogu1947】粉刷匠

时间:2017-08-07 00:10:32      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:class   情况   int   题目   das   没有   mem   背包   set   

先直接抛题解,等下在整理啦QwQ
我们先不管列,考虑每一行,很容易想到设f[i][j]表示**当前这一行**前i个数涂j次色所能正确涂色的最多格子数
再枚举一个k(j≤k≤i),考虑当前第k个格子到第i个格子的情况
我们要分情况讨论:
1. 第i个格子必须正确的刷,那么意味着k~i所刷的颜色必须是与i相同的颜色。我们用sum来表示k~i中与i颜色相同的格子个数,那么就可以递推:
$F[i][j]=max{F[k-1][j-1]+sum}(j≤k≤i)$
2. 第i个格子错误地刷,那么意味着k~i所刷的颜色必须是与i相反的颜色(总共只有两种颜色嘻嘻嘻),仍然用sum可以递推:
$F[i][j]=max{F[k-1][j-1]+i-k+1-sum}(j≤k≤i)$
以上两个取最大值即可。
但是,这道题到这里当然还没有做完——还有列没考虑呢!
其实很简单,我们记g[i][j]表示第i行涂j次色最多能正确涂的格子数,而题目说最多能涂t次色,是不是很容易想到背包问题!
至此就结束了,当然也有不少小的细节就见程序吧(解释上面应该差不多了,故代码就不注释了)

//F[i][j]
//1. F[k-1][j-1]+r
//2. F[k-1][j-1]+i-k+1+r
//r=k~i与i相同颜色的
//最后做背包 
#include<cstdio>
#include<cstring>
#define MAX(x,y) (x>y?x:y)
#define MIN(x,y) (x<y?x:y)
const int N=55,T=2505;
int n,m,t;
int b[N][N],f[N][T],mx[N],g[N][T],dp[T];
int main()
{
    scanf("%d%d%d",&n,&m,&t);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            scanf("%1d",&b[i][j]);
            if(j==1||b[i][j]!=b[i][j-1]) mx[i]++;
        }
    for(int l=1;l<=n;l++)
    {
        memset(f,0,sizeof(f));
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=mx[l];j++)
            {
                int r=0;
                for(int k=i;k>=j;k--)
                {
                    if(b[l][k]==b[l][i]) r++;
                    f[i][j]=MAX(f[i][j],f[k-1][j-1]+r);
                    f[i][j]=MAX(f[i][j],f[k-1][j-1]+i-k+1-r);
                }
                g[l][j]=MAX(g[l][j],f[i][j]);
            }
        }
    }
    for(int i=1;i<=n;i++)
        for(int j=t;j>=1;j--)
            for(int k=1;k<=MIN(j,mx[i]);k++)
                dp[j]=MAX(dp[j],dp[j-k]+g[i][k]);
    printf("%d",dp[t]);
}

 

【Luogu1947】粉刷匠

标签:class   情况   int   题目   das   没有   mem   背包   set   

原文地址:http://www.cnblogs.com/farway17/p/7296333.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!