题目描述
和所有人一样,奶牛喜欢变化。它们正在设想新造型的牧场。奶牛建筑师 Hei 想建造围有漂亮白色栅栏的三角形牧场。
她拥有 n 块木板,每块的长度是整数,
她想用所有的木板围成一个三角形使得牧场面积最大。
请帮助 Hei 小姐构造这样的牧场,并计算出这个最大牧场的面积。
输入格式
第 11行:一个整数 n;
第 2 到第 (n + 1)行,每行一个整数,第 (i+1) 行的整数li 表示第 i 块木板的长度。
输出格式
仅一个整数:最大牧场面积乘以 100 然后舍尾的结果。如果无法构建,输出 -1。
输入输出样例
输入 #1
5 1 1 3 3 4
输出 #1
692
说明/提示
样例输入输出 1 解释
692= ext{舍尾后的}(100 imes ext{三角形面积})692=舍尾后的(100×三角形面积),此三角形为等边三角形,边长为 44。
数据规模与约定
对于 100\%100% 的数据,保证 3le nle403≤n≤40,1le l_ile401≤li≤40
解析:
这是比较典型的01背包问题:
(1)首先定义状态
f[k][i][j]:前K条边是否恰好组成长分别为i和j的栅栏,是1,否0;
则f[k][i][j]=f[k-1][i-a[k]][j]//第k条边装在栅栏i
f[k-1][i][j-a[k]]//第k条边装在栅栏j
f[k-1][i][j]//第k条边装在第三条栅栏
#include<iostream> //#include<> #include<cmath> using namespace std; const int maxn=50; int f[900][900],a[maxn]; int n,tot=0; double ans=-1; bool Check(int x,int y){ int z=tot-x-y; return (x+y>z&&x+z>y&&y+z>x); } double Cal(int x,int y){ int z=tot-x-y; double p=(x+y+z)/2.0;//整数/整数 =整数 return sqrt(p*(p-x)*(p-y)*(p-z)); } int main(){ cin>>n; for(int i=1;i<=n;i++) {cin>>a[i];tot+=a[i];} int t=tot/2; f[0][0]=1; // for(int i=1;i<=n;i++)f[a[i]][0]=f[0][a[i]]=1; f[a[1]][0]=f[0][a[1]]=1;//第一条边,直接赋值 for(int k=2;k<=n;k++) for(int i=t;i>=1;i--) for(int j=t;j>=1;j--){ if(i>=a[k])f[i][j]|=f[i-a[k]][j]; if(j>=a[k])f[i][j]|=f[i][j-a[k]]; } for(int i=1;i<=t;i++){ for(int j=1;j<=t;j++){ if(f[i][j]&&Check(i,j))ans=max(ans,Cal(i,j)); // cout<<i<<" "<<j<<" "<<tot-i-j<<" "<<f[i][j]<<" "<<ans<<endl; } } if(ans>0)cout<<(int)(ans*100)<<endl; else cout<<ans<<endl; return 0; }