p1846

背包两联发...

这道题看上去和前一题相似,也是组合后求最值.依然可以开三位数组flag[i][f][j]表示该状态能否到达.然后跑20*2000*2000*2000.这样复杂度看来搞不了.考虑如何优化.

这道题和上一题不一样的地方在于:每个宝藏必须分给某个人.也就是说,对于第k个宝藏必须要求i+f+j==宝藏总大小才可以到达.这样我们可以减少一维了.

flag[f][j]表示第一个人f个第二个人j个的状态能否达到.刚开始当然flag[0][0]可以达到.然后对于每个宝藏t,如果flag[f][j]==1,那么flag[f+t][j]=flag[f][j+t]=flag[f][j]都能等于1.这三个式子分别表示t给第一二三个人的状态转移.

最后对于所有flag[f][j]=1的情况都可以拿来更新状态:ans=min(ans,max(f,max(j,sum-f-j)).

复杂度20*2000*2000不用优化.

int i,f,j,t,sum,ans;
int flag[2010][2010],n;
int main()
{
    flag[0][0]=1;
    n=read();
    for(i=1;i<=n;i++)
    {
        t=read();
        for(f=sum;f>=0;--f)
            for(j=sum;j>=0;--j)
                if(flag[f][j])
                    flag[f+t][j]=flag[f][j+t]=1;
        sum+=t;
    }
    ans=sum;
    for(f=0;f<=sum;++f)
        for(j=0;j<=sum;++j)
            if(flag[f][j])
                ans=min(ans,max(f,max(j,sum-f-j)));
    cout<<ans;
    return 0;
}
原文地址:https://www.cnblogs.com/qywyt/p/9988259.html