题意:给出一些木棍,必须全都用上,问能拼成的最大的三角形面积是多少。
分析:动态规划,f[i][j][k]表示用前i根木棍能否构成两条长度分别为j,k的边。
f[i][j][k] = f[i - 1][j][k];
if (j >= fence[i])
f[i][j][k] = f[i][j][k] || f[i - 1][j - fence[i]][k];
if (k >= fence[i])
f[i][j][k] = f[i][j][k] || f[i - 1][j][k - fence[i]];
以上过程只是构成两条边,第三条边的长度可以用总长度减去前两条边得到。 之前没有考虑这三条边是否能构成三角形。然后枚举所有的f[n][i][j]看能否构成三角形,并更新最大面积即可。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
usingnamespace std;
#define maxn 41
int fence[maxn];
bool f[maxn][805][805];
int sum =0, n;
bool ok(int a, int b)
{
int c = sum - a - b;
if (c < a + b && c > abs(a - b))
returntrue;
returnfalse;
}
double area(int a, int b, int c)
{
double p = sum /2.0;
return sqrt(p * (p - a) * (p - b) * (p - c));
}
int main()
{
//freopen("t.txt", "r", stdin);
scanf("%d", &n);
for (int i =1; i <= n; i++)
{
scanf("%d", &fence[i]);
sum += fence[i];
}
memset(f, 0, sizeof(f));
f[0][0][0] =true;
for (int i =1; i <= n; i++)
for (int j =0; j <= sum /2; j++)
for (int k =0; k <= sum /2; k++)
{
f[i][j][k] = f[i -1][j][k];
if (j >= fence[i])
f[i][j][k] = f[i][j][k] || f[i -1][j - fence[i]][k];
if (k >= fence[i])
f[i][j][k] = f[i][j][k] || f[i -1][j][k - fence[i]];
}
double ans =-1;
for (int i =1; i <= sum /2; i++)
for (int j =1; j <= sum /2; j++)
if (f[n][i][j] && ok(i, j))
ans = max(ans, area(i, j, sum - i - j));
if (ans >0)
ans *=100;
printf("%d\n", (int)ans);
return0;
}