• 【动态规划/二维背包问题】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 }
  • 相关阅读:
    Zookeeper实现配置中心
    Springboot
    分布式事务框架
    Spring 事件Application Event
    了解“事务机制” 过程
    mysql : 行锁,表锁,共享锁,排他锁,悲观锁,乐观锁
    数据库隔离级别和实现原理
    aop用于日志
    exceptionHandler統一处理异常
    mysql 点总结
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/4736245.html
Copyright © 2020-2023  润新知