【双重背包】三角形牧场 pasture

三角形牧场
pasture.pas/cpp

 

【问题描述】

       和所有人一样,奶牛喜欢变化。它们正在设想新造型的牧场。奶牛建筑师Hei想建造围有漂亮白色栅栏的三角形牧场。她拥有N(3≤N≤40)块木板,每块的长度Li(1≤Li≤40)都是整数,她想用所有的木板围成一个三角形使得牧场面积最大。

    请帮助Hei小姐构造这样的牧场,并计算出这个最大牧场的面积。

 

【输入】

       第1行:一个整数N

       第2..N+1行:每行包含一个整数,即是木板长度。

 

【输出】

       仅一个整数:最大牧场面积乘以100然后舍尾的结果。如果无法构建,输出-1。

 

【样例】

       pasture.in                                          pasture.out

       5                                               692

       1

       1

       3

       3

       4

 

【样例解释】

       692=舍尾后的(100×三角形面积),此三角形为等边三角形,边长为4。

 

 

用bool f[k,i,j]表示前k个木板能否同时表示出长度为 i 和 j ,是一个动规的双重背包

空间可能有点吃不消,用就地滚动省去k,变成f[i,j]

然后扫描所有的f[i,j],算出三边为 i,j,sum-i-j 的三角形的面积,取最大即可

C++ Code

/*
C++ Code
http://oijzh.cnblogs.com
*/
#include<cstdio>
#include<cmath>
#define MAXN 50

int n,a[MAXN],sum=0;
bool f[MAXN*MAXN][MAXN*MAXN];

void dp()
{
    f[0][0]=true;
    for(int i=1;i<=n;i++)
        for(int j=sum;j>=0;j--)
            for(int k=sum;k>=0;k--)
            {
                if(j>=a[i] && f[j-a[i]][k])f[j][k]=f[j-a[i]][k];
                if(k>=a[i] && f[j][k-a[i]])f[j][k]=f[j][k-a[i]];
            }
}

bool check(int a,int b,int c)
{
    if(a+b>c && a+c>b && b+c>a)return true;
    return false;
}

double get_area(int a,int b,int c)
{
    double p=(a+b+c)/2.0;
    return sqrt(p*(p-a)*(p-b)*(p-c));
}

int main()
{
    freopen("pasture.in","r",stdin);
    freopen("pasture.out","w",stdout);
    scanf("%d",&n);
    int i,j;
    for(i=1;i<=n;i++){scanf("%d",&a[i]);sum+=a[i];}
    dp();
    double ans=-1;
    for(i=1;i<=sum;i++)
        for(j=1;j<=sum;j++)
            if(f[i][j])
                if(check(i,j,sum-i-j))
                    ans>?=get_area(i,j,sum-i-j);
    if(ans==-1)printf("-1");
    else printf("%d",(int)(ans*100));
    return 0;
}

 

 

posted @ 2012-09-26 20:31  jiangzh  阅读(342)  评论(0编辑  收藏  举报