当前位置: 代码迷 >> 综合 >> dp poj1948 Triangular Pastures
  详细解决方案

dp poj1948 Triangular Pastures

热度:35   发布时间:2023-12-14 04:03:44.0

可能一开始会想到关于数量的dp,但是发现并不好操作

联想01背包,就可以发现,这题和01背包还是有很多共同特点的,我们为什么不拿长度来dp呢?


三角形的变长也有一些比较有趣的性质,,以前都没留意过

一般对于三角形的题目,都可以从这几个特点去思考

假如变长大小关系是a>=b>=c,那么会有b>=(a+b+c)/2 ,0<c<=(a+b+c)/3且会有c<=b

这使我们枚举变长成为了可能。

然后设dp[i][j]表示b为i,c为j这样的变长是否能同时组合出来,很容易列出方程

if(j >= A[i] && dp[j - A[i]][k]) dp[j][k] = 1;
if(k >= A[i] && dp[j][k - A[i]]) dp[j][k] = 1;

其中i是枚举所有的边。这个方法十分类似01背包,只是背包数从1个变成了2个而已~

然后a就可以通过sum-i-j求得,再验证是否能组成三角形,再更新面积,这题就差不多做完了

#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
#include<functional>
#include<algorithm>using namespace std;
typedef long long LL;
typedef pair<int, int> PII;const int MX = 1e3 + 5;
const int INF = 0x3f3f3f3f;int A[MX];
int dp[MX][MX];int getS(int a, int b, int c) {if(a >= b + c || b >= a + c || c >= a + b) return -1;double p = (a + b + c) / 2.0;return sqrt(p * (p - a) * (p - b) * (p - c)) * 100;
}int main() {int n;while(~scanf("%d", &n)) {memset(dp, 0, sizeof(dp));int sum = 0, V;for(int i = 1; i <= n; i++) {scanf("%d", &A[i]);sum += A[i];}V = sum / 2;int ans = -1;dp[0][0] = 1;for(int i = 1; i <= n; i++) {for(int j = V; j >= 0; j--) {for(int k = j; k >= 0; k--) {if(j >= A[i] && dp[j - A[i]][k]) dp[j][k] = 1;if(k >= A[i] && dp[j][k - A[i]]) dp[j][k] = 1;if(dp[j][k]) ans = max(ans, getS(sum - j - k, j, k));}}}printf("%d\n", ans);}return 0;
}