洛谷 P1284 三角形牧场 题解(背包+海伦公式)

题目链接

题目大意

给你 n块木板(n<=40),每块木板长度为\(l[i]<=40\)

每块木板都要用,求最大的三角形面积×100,答案直接舍去小数

题目思路

首先如果已知三条边的长度可以直接用海伦公式求出三角形面积

\(p=(a+b+c)/2\)

\(s=\sqrt{p*(p-a)*(p-b)*(p-c)}\)

显然你只要知道两条边的长度,你就可以直接剩下边的长度。

这个题目有点类似于给你几个数,你是否可以组成另一个数,这个就是显然的01背包

这个只是看能否组成两条边,只是多了一重循环,本质上还是01背包

代码

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#define fi first
#define se second
//#define int long long
#define debug printf(" I am here\n");
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=1e3+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-10;
int n,a[maxn],sum;
bool dp[maxn][maxn];
double cal(int a,int b,int c){
    double s=1.0*(a+b+c)/2;
    return sqrt(s*(s-a)*(s-b)*(s-c));
}
bool check(int a,int b,int c){
    if(a+b>c&&b+c>a&&a+c>b){
        return 1;
    }else{
        return 0;
    }
}
signed main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        sum+=a[i];
    }
    dp[0][0]=1;
    for(int i=1;i<=n;i++){
        for(int j=sum/2;j>=0;j--){
            for(int k=j;k>=0;k--){
                if((j>=a[i]&&dp[j-a[i]][k])||(k>=a[i]&&dp[j][k-a[i]])){
                    dp[j][k]=1;
                }
            }
        }
    }
    double ans=0;
    for(int j=sum/2;j>=0;j--){
        for(int k=j;k>=0;k--){
            int res=sum-j-k;
            if(!dp[j][k]) continue;
            if(res<0||(!check(j,k,res))) continue;
            ans=max(ans,cal(j,k,res));
        }
    }
    if(abs(ans-0)<eps){
        cout<<-1<<endl;
    }else{
        printf("%lld\n",(int)(100*ans));
    }
    return 0;
}

posted @ 2020-10-31 18:46  hunxuewangzi  阅读(180)  评论(0编辑  收藏  举报