构建双塔(dp-双进程)

构建双塔(dp-双进程)_第1张图片

f[i][j] 表示取前i块水晶、两塔差为j时较高塔的最大高度。

注意,这里的f[i][j]都是从上一阶段推得的。我们在面对第i块水晶时,它可能是从以下四种决策得来的:

f[i][j]=max(f[i-1][j]) ; 这块水晶被丢掉了。

f[i][j]=max(f[i-1][j+h[i]]) ; 这块水晶被给了上一个状态中较低的那座塔,且它未超过较高的塔,由图可知较高塔的最大高度是不变的。
构建双塔(dp-双进程)_第2张图片

f[i[][j]=max(f[i-1][j-h[i]]+h[i]) ; 这块水晶被给了上一个状态中较高的塔,由图可知,较高塔的值增加了h[i]。当然,此时我们要保证j>h[i]。

构建双塔(dp-双进程)_第3张图片
f[i][j]=max(f[i-1][h[i]-j]+j) ;这块水晶被给了上一阶段较低的塔,且它超过了较高塔。由图可知,较高塔的值增加了j。
构建双塔(dp-双进程)_第4张图片

美妙的code时间:

void init()
{
    read(n); 
    for(int i=1;i<=n;++i) read(h[i]),summ+=h[i];
}

void work()
{
    memset(f,-10,sizeof(f));//起初所有状态不合法 。 
    f[0][0]=0;
    for(int i=1;i<=n;++i)
        for(int j=0;j<=summ;++j)
        {
            f[i][j]=max(f[i-1][j],f[i-1][j+h[i]]);
            if(j>=h[i]) f[i][j]=max(f[i][j],f[i-1][j-h[i]]+h[i]);
            else f[i][j]=max(f[i][j],f[i-1][h[i]-j]+j);
        }
    if(f[n][0]) printf("%d",f[n][0]);//放了n块水晶且两塔差==0时即为所求。 
    else printf("Impossible");
}

起初看这题的时候存在误区,将f[i-1][j+h[i]]理解为把水晶给了当前的较高塔,实际上这样就不符合f[i][j]的设定了。应是上一状态对这一状态有影响。还是没有深刻理解状态转移的含义啊。

你可能感兴趣的:(双进程。)