题目描述

和所有人一样,奶牛喜欢变化。它们正在设想新造型的牧场。奶牛建筑师 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=\text{舍尾后的}(100\times\text{三角形面积})692=舍尾后的(100×三角形面积),此三角形为等边三角形,边长为 44。

数据规模与约定

对于 100\%100% 的数据,保证 3\le n\le403n40,1\le l_i\le401li40

解析:

这是比较典型的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;
}