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;
}

  

posted @ 2015-02-13 22:08  chenjunjie1994  阅读(180)  评论(0编辑  收藏  举报