您的位置:首页 > Web前端 > AngularJS

[POJ] 1948 Triangular Pastures (DP)

2016-03-15 09:25 585 查看
题目地址:http://poj.org/problem?id=1948

题目大意:

给N条边,把这些边组成一个三角形,问面积最大是多少?必须把所有边都用上。

解题思路:

根据题意周长c已知,求组合三边长使得三角形面积最大。如果直接DFS的话,每次考虑每根木棍放在哪一条边上,爆搜,可以加上每条边不会大于周长的一半的剪枝。根据数据规模,仍会超时,所以可以考虑采用动态规划。因为周长c已知,所以只需考虑其中两条边即可。类似二维0-1背包的做法,开一个二维判定数组f[i][j],i代表第一条边长为i,j为第二条边长为j,则第三条边长为c-i-j,判定所有情况。最后验证即可。因为三角形每条边长不可能超过周长的一半,所以枚举i,j最大到c/2即可。最后注意结果小数部分不是四舍五入,而是直接截断的,所以可以利用强制转化。

DP代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<math.h>
using namespace std;
const int N=41*41;
int f

;
int a[41],c=0,n;

int main()
{

scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
c+=a[i];
}

memset(f,0,sizeof(f));
f[0][0]=1;
for(int i=1;i<=n;i++){
for(int j=c/2+1;j>=0;j--){
for(int k=c/2+1;k>=0;k--){
if(j-a[i]>=0 && f[j-a[i]][k]){
f[j][k]=1;
}
if(k-a[i]>=0 && f[j][k-a[i]]){
f[j][k]=1;
}
}
}
}

double s=0;
for(int i=c/2+1;i>=0;i--){
for(int j=c/2+1;j>=0;j--){
if(f[i][j]){
double la=i,lb=j,lc=c-i-j;
double p=(la+lb+lc)/2.0;
if(sqrt(p*(p-la)*(p-lb)*(p-lc))>s){
s=sqrt(p*(p-la)*(p-lb)*(p-lc));
}
}
}
}

printf("%d\n",s==0 ? -1 : (int)(s*100));

return 0;
}


DFS代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<math.h>
using namespace std;
const int N=53;
int n,sum,la=0,lb=0,c=0,lc;
int a
,f
;
double s=0;

void dfs(int k)
{
if(la>c/2 || lb>c/2 || lc>c/2) return ;
if(k==n){
if(la+lb>lc && la+lc>lb && lb+lc>la){
double p=(la+lb+lc)/2.0;
if(sqrt(p*(p-la)*(p-lb)*(p-lc))>s){
s=sqrt(p*(p-la)*(p-lb)*(p-lc));
}
}
return ;
}
for(int i=0;i<n;i++){
if(!f[i])
for(int j=0;j<3;j++){
if(j==0){
la+=a[i];
f[i]=1;
dfs(k+1);
f[i]=0;
la-=a[i];
}
if(j==1){
lb+=a[i];
f[i]=1;
dfs(k+1);
f[i]=0;
lb-=a[i];
}
if(j==2){
lc+=a[i];
f[i]=1;
dfs(k+1);
f[i]=0;
lc-=a[i];
}
}
}
}
int main()
{
memset(f,0,sizeof(f));
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
c+=a[i];
}
dfs(0);
printf("%d\n",s==0 ? -1:(int)(s*100));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: