有的时候需要一点解陌生题目的能力

描述

2001年9月11日,一场突发的灾难将纽约世界贸易中心大厦夷为平地,Mr. F曾亲眼目睹了这次灾难。为了纪念“9?11”事件,Mr. F决定自己用水晶来搭建一座双塔。

Mr. F有N块水晶,每块水晶有一个高度,他想用这N块水晶搭建两座有同样高度的塔,使他们成为一座双塔,Mr. F可以从这N块水晶中任取M(1≤M≤N)块来搭建。但是他不知道能否使两座塔有同样的高度,也不知道如果能搭建成一座双塔,这座双塔的最大高度是多少。所以他来请你帮忙。

给定水晶的数量N(1≤N≤100)和每块水晶的高度Hi(N块水晶高度的总和不超过2000),你的任务是判断Mr. F能否用这些水晶搭建成一座双塔(两座塔有同样的高度),如果能,则输出所能搭建的双塔的最大高度,否则输出“Impossible”。

格式

输入格式

输入的第一行为一个数N,表示水晶的数量。第二行为N个数,第i个数表示第i个水晶的高度。
输出格式

输出仅包含一行,如果能搭成一座双塔,则输出双塔的最大高度,否则输出一个字符串“Impossible”。

样例1

样例输入1

5
1 3 4 5 2

样例输出1

7

来源

某校NOIP模拟题

扯淡的 题解

哇,刚刚看到这个题好懵逼啊,看了一下数据范围,好像是2重循环…然后就想到在背包中加一个维度来维护两塔的差值,然后f[i][j]代表用前i个水晶,两塔差值为j时,所得到的最大高度.
对于每一个i,都有三个决策:
1.放第i块水晶到高的一个塔上.
2.放第i块水晶到矮的塔上.
3.不放第i块水晶
于是就搞粗来方程啦~
但是我好像并不能写出了23333
嗯就是用以前的状态推出当前状态是比较困难的…于是小仙女般的我就想到用填表法啦~以当前状态出发,推出三种状态,填上三个数…

沙茶的 代码:

#include<cstdio>
#include<cstring>
#define max(a,b) ((a)>(b)?(a):(b))
#define MAXN (100+5)
#define MAXH (2000+5)
#define MAXC (2000+5)
#define INF (2000)
int f[MAXN][2*MAXC];//f[i][j]means used i diamond && the (upper-lower) is j &&the higher hight is f[i][j]
int a[MAXN];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i=0;i<=n;i++)
    {
        for(int j=0;j<=MAXC;j++)
        {
            f[i][j]=-INF;
        }
    }
    f[0][0]=0;
    for(int i=0;i<=n;i++)
    {
        for(int j=MAXC;j>=0;j--)
        {
//            f[i][j]=f[i-1][j];
            if(f[i][j]>=0)//从已知的状态向后推
            {
                f[i+1][j]=max(f[i+1][j],f[i][j]);//不放
                f[i+1][a[i+1]+j]=max(f[i+1][a[i+1]+j],f[i][j]+a[i+1]);//放在较高的塔上
                if(a[i+1]>=j)//放在较低的塔上
                {
                    f[i+1][a[i+1]-j]=max(f[i+1][a[i+1]-j],(f[i][j]+a[i+1]-j));//两塔之差小于当前水晶,所以放了该水晶两塔的高低关系将对调
                }
                else
                {
                    f[i+1][j-a[i+1]]=max(f[i+1][j-a[i+1]],f[i][j]);//两塔之差大于当前水晶,即使放了该水晶,高低关系也不变,高的依然高,矮的依然矮(就像我穿上增高鞋也没有gjp高QAQ)
                }
            }
        }
    }
    /*for(int i=0;i<=n;i++)
    {
        printf("%d:\t",i);
        for(int j=0; j<=7;j++)
        {
            printf("%d\t",f[i][j]);
        }
        puts("");
    }*/
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        ans=max(ans,f[i][0]);//要求两塔高度相等,即差值为0
    }
    if(ans)
    printf("%d",ans);
    else
    printf("Impossible");
    return 0;
}

by 没有dalao们可爱的 Cansult
这里写图片描述