POJ 1948
这道题我记得是携程比赛上的一道。
开始时想直接设面积,但发现不可以,改设能否构成三角形。设dp[i][j][k]为前i根木棍构成边长为j和k的三角形,那么转移可以为dp[i][j][k]=dp[i-1][j-len[i]][k]|dp[i-1][j][k-len[i]]。当发现可以构成三角形时,再用海伦公式求出三角形面积即可。
由于边长不应该超过总长一半,所以,DP范围只在一半即可。
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; bool dp[810][810]; int n; int len[50]; int main(){ while(scanf("%d",&n)!=EOF){ double sum,p; sum=0; for(int i=1;i<=n;i++){ scanf("%d",&len[i]); sum+=len[i]; } p=sum/2; memset(dp,false,sizeof(dp)); dp[0][0]=true; for(int i=1;i<=n;i++){ for(int j=p;j>=0;j--){ for(int k=p;k>=0;k--){ if(j>=len[i]){ dp[j][k]=dp[j][k]|dp[j-len[i]][k]; } if(k>=len[i]) dp[j][k]=dp[j][k]|dp[j][k-len[i]]; } } } double ans=-1; for(int i=0;i<=p;i++){ for(int j=0;j<=p;j++){ if(dp[i][j]){ double area=sqrt(p*(p-i)*(p-j)*(p-(sum-i-j))); ans=max(ans,area); } } } if(ans>0){ printf("%d\n",int(ans*100)); } else printf("-1\n"); } return 0; }