《三角形牧场》DP题解

题目描述

奶牛建筑师Hei想建造围有漂亮白色栅栏的三角形牧场。她拥有N(3≤N≤40)块木板,每块的长度Li(1≤Li≤40)都是整数,她想用所有的木板围成一个三角形使得牧场面

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

输入格式

第1行:一个整数N。

第2…N+1行:每行包含一个整数,即是木板长度。

输出格式

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

样例输入

5
1
1
3
3
4

样例输出

692

思路

看到这道题目,我的第一感觉是用贪心做:使三边更加接近。这样很容易找到反例。

不妨令 s u m sum =所有木板的长度总和,易知:如果枚举三角形的两边 i i , j j ,那么第三边: k = s u m i j k=sum-i-j 。又因为 3 < = N < = 40 3<=N<=40 ,我们便可以想到暴力枚举 i i j j

但是万一给定的木板凑不齐 i i j j k k 怎么办?这里像不像DP可行性问题的板子?

所以定义bool类型数组 d p [ i ] [ j ] dp[i][j] 标记给定三角形的i,j两边能不能被给定的木板凑齐

对于每个 a [ n u m ] a[num] ,如果 d p [ i ] [ j a [ n u m ] ] = = t r u e dp[i][j-a[num]]==true ,即给定木板可以凑出 i i j a [ n u m ] j-a[num] , s u m i j + a [ n u m ] sum-i-j+a[num] ,那么给定木板便一定可以凑出 i i j j s u m i j sum-i-j ,即 d p [ i ] [ j ] dp[i][j] t r u e true

我们则可以得出核心代码

if(j >= a[i]) dp[j][k] |= dp[j - a[i]][k];
if(k >= a[i]) dp[j][k] |= dp[j][k - a[i]];

当然,我们还需:

1.判别这三边是否能组成三角形。
2.使用求三角形面积的海伦公式…

这些都是很容易想到的。

代码

#include <cstdio>
#include <algorithm>
#include <climits>
#include <cmath>
#include <cstring>
#define LL long long
using namespace std;
const int MAXN = 45, MAXX = 40 * 40 + 5;
int a[MAXN], dp[MAXX][MAXX], sum;
double t;
bool bol(int x, int y, int z) {
	if((x + y) <= z) return 1;
	if((x + z) <= y) return 1;
	if((y + z) <= x) return 1;
	return 0;
}
double hl(int x, int y, int z) {
	double ans = sqrt(t * (t - x) * (t - y) * (t - z));
	return ans;
}
int main() {
	int n, l;
	double maxx = -1;
	scanf("%d", &n);
	for(int i = 1; i <= n; i ++) {
		scanf("%d", &a[i]);
		sum += a[i];
	}
	t = sum / 2.0;
	dp[0][0] = 1;
	for(int i = 1; i <= n; i ++) {
		for(int j = sum / 2; j >= 0; j --) {
			for(int k = j; k >= 0; k --) {
				if(j >= a[i]) dp[j][k] |= dp[j - a[i]][k];
				if(k >= a[i]) dp[j][k] |= dp[j][k - a[i]];
			}
		}
	}
	for(int i = sum / 2; i > 0; i --) {
		for(int j = i; j > 0; j --) {
			l = sum - i - j;
			if(l < 0) continue;
			if(bol(i, j, l) || (!dp[i][j])) continue;
			maxx = max(maxx, hl(i, j, l));	
		}
	}
	if(maxx == -1) {
		printf("-1");
		return 0;
	}
	printf("%d", int(floor(maxx * 100)));
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Clever_Hard/article/details/106591621
今日推荐