【动态规划/二维背包问题】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 }
时间: 2024-09-30 11:17:29

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

HDU3496Watch The Movie (二维背包问题)

题目要求: 输入:三个整数N,M,L,分别代表想看的电影书,店里出售的电影数目,最长可看的时间,接下来给出N个电影各自的时长和价值 输出:能看到的最大价值,如果没有满足条件的输出0 解题思路: 二维背包问题,一个限制是时长之和有最大值,另一个是电影的数目有要求的值,为了方便用二维背包的思路求解,可以将第二个条件先看做是数目的最大值为M去求解,最后再找数目恰好为M的价值即可. 状态转移方程为:dp[i][j]=max{dp[i][j],dp[i-1][j-t[k]]+v[k]} 代码如下: # i

C语言-二维背包问题

二维费用背包问题 问题: 二维费用的背包问题是指:对于每件物品,具有两种不同的费用:选择这件物品必须同时付出这两种代价:对于每种代价都有 一个可付出的最大值(背包容量).问怎样选择物品可以得到最大的价值.设这两种代价分别为代价1和代价2,第i件物品所需的两种代价分别为a[i]和 b[i].两种代价可付出的最大值(两种背包容量)分别为V和U.物品的价值为w[i]. 分析: 费用加了一维,只需状态也加一维即可.设f[i][v][u]表示前i件物品付出两种代价分别为v和u时可获得的最大价值.状态转移方

HDU2159 FATE(二维背包问题)

题目要求: Problem Description 最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务.久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完这最后一级.现在的问题是,xhd升掉最后一级还需n的经验值,xhd还留有m的忍耐度,每杀一个怪xhd会得到相应的经验,并减掉相应的忍耐度.当忍耐度降到0或者0以下时,xhd就不会玩这游戏.xhd还说了他最多只杀s只怪.请问他能升掉这最后一级吗? Input 输入数据有多组,对于每组数据第一行输入n,m

二维图像的三角形变换算法解释

http://blog.csdn.net/aqua_aqua/article/details/407660 对于二维图像的变形,最简单直接的方式就是将需要变形的不规则区域进行三角形划分,使复杂多边形由1到N个三角形组成,那么最终的变形动作也就转化为这些三角形变形. 三角形变形,就是将一个三角形通过某种变换变成另一个三角形,同时也要保证在源三角形中的点能够正确映射到目标三角形中合适的位置.如下图所示: 图中△ABC是源三角形,Z点是源三角形中的任意一点.△abc为目标三角形,而z点就是源三角形中Z

【洛谷】【动态规划(二维)】P1508 Likecloud-吃、吃、吃

[题目描述:] 正处在某一特定时期之中的李大水牛由于消化系统比较发达,最近一直处在饥饿的状态中.某日上课,正当他饿得头昏眼花之时,眼前突然闪现出了一个n*m(n and m<=200)的矩型的巨型大餐桌,而自己正处在这个大餐桌的一侧的中点下边.餐桌被划分为了n*m个小方格,每一个方格中都有一个圆形的巨型大餐盘,上面盛满了令李大水牛朝思暮想的食物.李大水牛已将餐桌上所有的食物按其所能提供的能量打了分(有些是负的,因为吃了要拉肚子),他决定从自己所处的位置吃到餐桌的另一侧,但他吃东西有一个习惯——只

二维费用背包问题(背包九讲)

------------------------------------------ 前言: 对于一些背包问题,重点还是在于如何找出"背包容量"和"各种代价",以及价值,如此问题便迎刃而解了.下午 打篮球居然下冰雹了,悲催了.... ------------------------------------------ 问题: 二维费用的背包问题是指:对于每件物品,具有两种不同的费用:选择这件物品必须同时付出这两种代价:对于每种代价都有 一个可付出的最大值(背包容量)

hdu2159 FATE 二维的完全背包

//这题典型的二维背包问题,因为题目说了每种怪的数量无限 //先开始的时候我想定义一个三维的dp,dp[i][j][k]表示前i种 //怪杀死j只剩余耐久点为dp[i][j][k]经验的最大值,然后状态 //方程就可以得到为dp[i][j][k] = max (dp[i-1][j][k],dp[i][j-1][k-b[i]]+a[i]); //这和完全背包的方程同出一辙,只是最后的答案我却不太清楚怎么找大, //最后看了一下题解,原来我的想法是对的,但最终的结果只要找到满足条件的最大的j就可以啦

SPOJ 181 - Scuba diver 二维背包

潜水员要潜水,给出n个气缸(1<=n<=1000),每个气缸中有氧气量为ti,氮气量为ai,气缸重量为wi(1<=ti<=21,1<=ai<=79,1<=wi<=800).现在潜水员需要量为t的氧气,量为a的氮气(1<=t<=21,1<=a<=79),问选哪些气缸,使得重量最小. [背包]二维背包问题,不同的是这个要选的物品占两种容量至少为t和a. 设dp[i][j][k]为氧气量为j,氮气量为k时的最小重量 dp[i][j][k]=

二维费用的背包问题

问题 二维费用的背包问题是指:对于每件物品,具有两种不同的费用:选择这件物品必须同时付出这两种代价:对于每种代价都有一个可付出的最大值(背包容量). 问怎样选择物品可以得到最大的价值. 设这两种代价分别为代价1和代价2,第i件物品所需的两种代价分别为a[i]和b[i].两种代价可付出的最大值(两种背包容量)分别为V和U.物品的价值为c[i]. 算法 费用加了一维,只需状态也加一维即可. 设f[i][v][u]表示前i件物品付出两种代价分别为v和u时可获得的最大价值. 状态转移方程就是:f [i]