一、题目
二、分析
sum:所有边长的和
dp[a][b]:能否组成长度分别为a,b,sum-a-b的三条边
状态转移方程:
在循环枚举a,b时注意枚举的顺序。
这里有个小知识点值得一提:
状态转移方程大致有两种推到方式:
第一种是当前状态由某个状态推出(逆向)
第二种是当前状态可以推出某个状态(正向)
大部分dp题是使用逆向推导比较方便,但有些题目使用正向容易,所以需要根据实际情况确定使用哪种推导方式。
以上是动态规划的分析过程,下面分析题目所涉及的三角形知识。
判断长度分别为a,b,c的三条边能否组成三角形:
bool If_found(int a, int b, int c)
{
return a + b > c && a + c > b && b + c > a;
}
已知三角形三条边求三角形面积(海伦公式):
double area(int a, int b, int c)
{
double p = sum / 2.0;
return pow(p * (p - a) * (p - b) * (p - c), 0.5);
}
三、代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1610;
bool dp[N][N];
int n;
int l[N];
int sum;
bool If_found(int a, int b, int c)
{
return a + b > c && a + c > b && b + c > a;
}
double area(int a, int b, int c)
{
double p = sum / 2.0;
return pow(p * (p - a) * (p - b) * (p - c), 0.5);
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> l[i];
sum += l[i];
}
dp[0][0] = true;
for (int i = 1; i <= n; i++)
{
for (int a = sum; a >= 0; a--)
{
for (int b = sum; b >=0 ; b--)
{
if (dp[a][b])
{
dp[a + l[i]][b] = true;
dp[a][b + l[i]] = true;
}
}
}
}
double s = -1;
for (int a = 1; a < sum; a++)
{
for (int b = 1; b < sum; b++)
{
int c = sum - a - b;
if (dp[a][b] && If_found(a, b, c))
s = max(s, area(a, b, c));
}
}
if(s>0)
cout << int(s * 100) << endl;
else
cout<<s<<endl;
return 0;
}