【动态规划/二维背包问题】mr355-三角形牧场

应该也是USACO的题目?同样没有找到具体出处。

【题目大意】

和所有人一样,奶牛喜欢变化。它们正在设想新造型牧场。奶牛建筑师Hei想建造围有漂亮白色栅栏的三角形牧场。她拥有N(3≤N≤40)块木板,每块的长度L(1≤L≤40)都是整数,她想用所有的木板围成一个三角形使得牧场面积最大。

请帮助Hei小姐构造这样的牧场,并计算出这个最大牧场的面积。

[输入]

第1行:一个整数N。

第2行起:包含N个用空格分隔的整数,即是每块木板的长度。

[输出]

仅一个整数:最大牧场面积乘以100然后舍尾的结果。如果无法构建,输出-1。

[样例输入]

mr355.in

5

1 1 3 3 4

[样例输出]

692

【思路】

二维背包问题,dp[i][ja][jb],取到第i块木板时能否组成ja、jb长度。预处理时,dp[0][0][0]=1,即取到第0块木板做成两边长度为0是可能的。这里有一个优化,tot表示当前已经取到的i块木板的总长度,ja、jb的长度判断只需从0..tot,如果当前dp[i-1][ja][jb]能取到,则dp[i][ja][jb],dp[i][ja+leng][jb],dp[i][ja][jb+leng]均能取到。这个时候我们发现,当前的dp[i]只和dp[i-1]相关,所以可以更改成滚动数组。

最后依次枚举前两边长度,并相减得出最后一边长度,如果能够组成三角形,则用海伦公式算出面积与最小值比较。

【易错点】

注意精度问题!double p=(a+b+c)*1.0/2,一定不能忘记要乘上0.1,否则会被视作整除去尾掉的!

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 using namespace std;
 5 const int MAXN=40+5;
 6 int n,tot;
 7 int leng[MAXN];
 8 int dp[2][1600][1600];
 9 /*取到第几块木板,后面为前两块木板,这里用了滚动数组*/
10 
11 void init()
12 {
13     scanf("%d",&n);
14     for (int i=0;i<n;i++) scanf("%d",&leng[i]);
15 }
16 
17 void dpprocess()
18 {
19     memset(dp,0,sizeof(dp));
20     dp[0][0][0]=1;
21     tot=0;
22     /*当前已经取到的木块总长度*/
23     for (int k=0;k<n;k++)
24     {
25         for (int i=0;i<=tot;i++)
26             for (int j=i;j<=tot-i;j++)
27             {
28                 if (dp[k%2][i][j]==1)
29                 {
30                     dp[(k+1)%2][i][j]=1;
31                     dp[(k+1)%2][i+leng[k]][j]=1;
32                     dp[(k+1)%2][i][j+leng[k]]=1;
33                 }
34             }
35         tot+=leng[k];
36     }
37 }
38 
39 void print()
40 {
41     int ans=-1;
42     for (int a=0;a<=tot;a++)
43         for (int b=a;b<=tot-a;b++)
44         {
45             if (dp[n%2][a][b]==1)
46             {
47                 int c=tot-a-b;
48                 if (a<b+c && b<a+c && c<a+b)
49                 {
50                     double p=(a+b+c)*1.0/2;
51                     double s=sqrt(p*(p-a)*(p-b)*(p-c))*100;
52                     if (s>ans) 
53                     {
54                         ans=s;
55                     }
56                 }
57             }
58         } 
59     cout<<ans<<endl;
60 }
61 
62 int main()
63 {
64     freopen("mr355.in9","r",stdin);
65     freopen("mr355.ou9","w",stdout);
66     init();
67     dpprocess();
68     print();
69     return 0;
70 }
原文地址:https://www.cnblogs.com/iiyiyi/p/4736245.html