POJ 1948 Triangular Pastures 【经典问题 - 二维01背包求最大三角形】

传送门
// 题意 : 现在有n根木棍, 要求把这些木棍全部用上, 能组成的最大三角形面积是多少. 不能组成输出-1.

思路: 这个问题就很经典了, 我们首先看数据范围, 最多40根, 每根最长40, 那么周长最长1600, 那么我们就要枚举到1600?显然不是的, 我们可以利用好三角形的边长特点, 可以发现最长的边是周长的一半即800, 所以我们设dp[i][j][k] 代表前i个木棍存在两边长为j, k的方案, 那么转移方程就是:
dp[i][j][k] = dp[i-1][j-a[i]][k] || dp[i-1][j][k-a[i]], 前提j >= a[i] || k >= a[i], 很明显我们可以进行压维, 那么就是需要逆向进行, 然后更新完dp数组后, 最后在扫一遍取第三条边存在的方案中取面积最大的即可….

AC Code

const int maxn = 40+5;
int dp[805][805];
int a[maxn];
bool ok(int a, int b, int c) {
    return (a+b) > c && (a+c) > b && (b+c) > a;
}
int cal(int a, int b, int c) {
    db p = 1.0*(a+b+c)/2;
    return sqrt(p*(p-a)*(p-b)*(p-c))*100;
}
void solve()
{
    int n, s = 0;
    scanf("%d", &n);
    for (int i = 1 ; i <= n ; i ++) {
        scanf("%d", a+i);
        s += a[i];
    }
    int tot = s/2; dp[0][0] = 1;
    for (int i = 1 ; i <= n ; i ++) {
        for (int j = tot ; j >= 0 ; j --) {
            for (int k = tot ; k >= 0 ; k --) {
                if ((j >= a[i] && dp[j-a[i]][k]) || (k >= a[i] && dp[j][k-a[i]]))
                    dp[j][k] = 1;
            }
        }
    }

    int ans = -1;
    for (int i = 0 ; i <= tot ; i ++) {
        for (int j = 0 ; j <= tot ; j ++) {
            if (dp[i][j] && ok(i, j, s-i-j) && ans < cal(i, j, s-i-j)) {
                ans = cal(i, j, s-i-j);
            }

        }
    }
    printf("%d\n", ans);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值