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开始也不会错,只是多跑一点时间

 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 }
View Code

 

posted @ 2020-03-30 10:08  古比  阅读(244)  评论(0编辑  收藏  举报