P1284 三角形牧场
题意:给出n个木板,让我们用掉所有的模板,使其凑成一个三角形,求出最大面积
凑不出三角形输出-1
思路:每一条边的长度不超过40,最多40条边,于是周长最大值为1600;
那么单边长度不超过800
总共三条边,第三条边可以通过周长减其余两条边得出
于是我们可以通过枚举其中两条边暴力找出所有方案,再择优
那么怎么枚举呢?我们开数组dp【i】【j】 表示第1条边长为i 第2条边长为j
于是将i跟j从大到小枚举(为何从大到小,因为从小到大会重复使用某一条边,借鉴01背包)
我们再枚举方案,先判断每个方案是否能凑成三角形,再计算是否能够作为答案即可
注:为何枚举第二条边k是从j开始枚举? 因为假如从half开始的话,会将重复方案,比如i=1 j=3 i=3 j=1
当然从half开始也不会错,只是多跑一点时间
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=800+10; 4 int a[maxn]; 5 bool f[maxn][maxn]; 6 bool judge(int i,int j,int k) 7 { 8 if(i+j>k&&i+k>j&&k+j>i)return true; 9 else return false; 10 }//判断是否可以构成三角形 11 12 double Helen(double i,double j,double k) 13 { 14 double p; 15 p=(i+j+k)/2; 16 double tmp=sqrt(p*(p-i)*(p-j)*(p-k)); 17 return tmp; 18 }//海伦公式算面积 19 20 int main() 21 { 22 int n; 23 scanf("%d",&n); 24 memset(f,false,sizeof(f)); 25 int tot=0; 26 for(int i=1;i<=n;i++){ 27 scanf("%d",&a[i]); 28 tot+=a[i];//处理出周长 29 } 30 int half=tot/2;//从周长一半开始循环,很显然三角形的每一条边不可以超过周长的一半 31 f[0][0]=1; 32 for(int i=1;i<=n;i++){ 33 for(int j=half;j>=0;j--){ 34 for(int k=j;k>=0;k--){ 35 if(j>=a[i]&&f[j-a[i]][k] || k>=a[i]&&f[j][k-a[i]]) 36 f[j][k]=1;//若是能够加上这根小木棒则赋值为1,f[j][k]表示能否组成边长为j,k的边,也要注意判断它加过来之前的那个f是否存在 37 } 38 } 39 } 40 double maxx=-1; 41 for(int i=half;i>=1;i--){ 42 for(int j=i;j>=1;j--){ 43 if(f[i][j]){ 44 int k=tot-i-j; 45 if(judge(i,j,k)){ 46 double val=Helen(i,j,k); 47 maxx=max(maxx,val); 48 } 49 } 50 } 51 } 52 if(maxx==-1) printf("-1\n"); 53 else cout<<(int)(maxx*100)<<endl;//记得最后结果是整数并且要 *100 54 return 0; 55 }