题意:给出N条长度不大于40的线段,要求分成三部分,用这3部分的长度总和作为3条边,要求围成的三角形面积最大。
想了很久,WA十多次,终于AC了,二维背包,dp[x][i][j]代表加入第x个数时第条一边位i时候第二条边为j时候的可行性。
状态转移方程:dp[ i ][ j ][ k ] = dp[i - 1][ j + s[i]][ k ] | dp[i - 1][ j ][ k + s[i] ]
#include<iostream>
#include<map>
#include<vector>
#include<string>
#include<algorithm>
#include<stdio.h>
#include<cstring>
#include<set>
#include<cmath>
using namespace std;
#define N 805
#define M 105
int s[M];
bool dp[2][N][N];
int num;
int heron(int a,int b,int c)
{
if(a == 0 || b == 0 || c == 0)
return -1;
if(a > b)
{
a ^= b;
b ^= a;
a ^= b;
}
if(b > c)
{
b ^= c;
c ^= b;
b ^= c;
}
if(c >= a + b)
return -1;
double p = (double)(a + b + c)/2.0;
double h = sqrt((p*(p - a)*(p - b)*(p - c)));
int sum = h*100;
return sum;
}
int main()
{
int i,j,k;
int n,m,o;
while( cin>>n )
{
memset(dp,0,sizeof(dp));
num = 0;
for(i = 1;i <= n;i++)
{
cin>>s[i];
num += s[i];
}
int ans = -1;
dp[0][0][0] = 1;
for(i = 1,o = 0;i <= n;i++)
{
o = 1 - o;
for(j = 0;j <= num/2;j++)
{
for(k = 0;k <= num/2;k++)
{
dp[o][j][k] = 0;
}
}
for(j = 0;j <= num/2;j++)
{
for(k = 0;k <= num/2;k++)
{
if(dp[1 - o][j][k] == 1)
{
dp[o][j][k] = 1;
if(j + s[i] <= num/2 && dp[1 - o][j + s[i]][k] == 0)
{
dp[o][j + s[i]][k] = 1;
ans = max(ans,heron(j + s[i],k,num - j - k - s[i]));
}
if(k + s[i] <= num/2 && dp[1 - o][j + s[i]][k] == 0)
{
dp[o][j][k + s[i]] = 1;
ans = max(ans,heron(j,k + s[i],num - j - k - s[i]));
}
}
}
}
}
cout<<ans<<endl;
}
return 0;
}
不知道会不会MLE,所以用了滚动数组,修修改改,剪枝剪了一下午,终于过了,实力还是不足啊,再接再厉!