当前位置:编程学习 > C/C++ >>

poj 1948 Triangular Pastures (dp二维背包)

 


题目大意:

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

 


思路:

对于已知周长的三角形,我们只要知道两条边的长度变可推出第三条边,所以可以得到状态方程:
f[i][j][k] 表示用前i条边,能否组成长度为j和k的两条边
初始化f[0][0][0] = true;
f[i][j][k] = f[i-1][j-len[i]][k] || f[i-1][j][k-len[i]];
如果f[i][j][k]=true,那么就计算以j,k,sum-j-k为三条边能否组成三角形,如果可以就用海易做图式计算面积。


由于如果要开三维数组的话,要开f[40][1600][1600],明显是要MLE的,所以要降成二维的,
而时间复杂度40*1600*1600,如果没有优化直接上,是要TLE的。
所以要优化,根据优化的程度,运行时间可以再100MS~1000MS之间:

1. f[i][j] 和 f[j][i]是相同的两个三角形,所以递推时可以让 j>=i
2. 对于每条边,一定是小于周长的一半
3. 枚举到第i条边时, 前i条边不可能组成大于等于sum[i] (sum[i]=len[1]+...+len[i])的长度

 

 

优化了一下时间到了100MS+

 


代码:


[cpp]
#include<iostream>  
#include<cstdio>  
#include<cmath>  
#include<algorithm>  
#include<cstring>  
#include<vector>  
#define SQ(x) ((x)*(x))  
#define MP make_pair  
const int INF = 0x3f3f3f3f; 
const double PI = acos(-1.0); 
typedef long long int64; 
using namespace std; 
 
const int MAXN = 42; 
int n, m; 
int len[MAXN], sum[MAXN]; 
bool f[1602][1602]; 
 
inline bool isTriangle(double e[3]){ 
    if(e[2] < e[1]){ 
        swap(e[2], e[1]); 
        if(e[1] < e[0]) swap(e[0], e[1]); 
    } 
    return e[0]+e[1] > e[2]; 

 
inline double getArea(double e[3]){ 
    if(!isTriangle(e)) return -1; 
    double p = sum[n]/2.0; 
    return sqrt(p*(p-e[0])*(p-e[1])*(p-e[2])); 

 
int main(){ 
    scanf("%d", &n); 
    for(int i=1; i<=n; ++i){ 
        scanf("%d", &len[i]); 
        sum[i] = sum[i-1]+len[i]; 
    } 
 
    memset(f, 0, sizeof(f)); 
    f[0][0] = true; 
 
    double ans = -1; 
    double e[3]; 
    for(int i=1; i<=n; ++i){ 
        for(int v1=min(sum[i],sum[n]>>1); v1>=0; --v1){ 
            for(int v2=min(sum[i]-v1,sum[n]>>1); v2>=v1; --v2)if(v1+v2<sum[n]){ 
                e[0] = v1; e[1] =v2; e[2] = sum[n]-v1-v2;          
                if(v1-len[i]>= 0 && f[v1-len[i]][v2]){ 
                    f[v1][v2] = true; 
                } 
                if(!f[v1][v2] && v2-len[i]>=0 && f[v1][v2-len[i]]){ 
                    f[v1][v2] = true; 
                } 
                if(f[v1][v2]){ 
                    ans = max(ans, getArea(e));              
                } 
            }  
        } 
    } 
    if(ans < 0) puts("-1"); 
    else printf("%d\n", (int)(100*ans)); 
 
    return 0; 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<vector>
#define SQ(x) ((x)*(x))
#define MP make_pair
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
typedef long long int64;
using namespace std;

const int MAXN = 42;
int n, m;
int len[MAXN], sum[MAXN];
bool f[1602][1602];

inline bool isTriangle(double e[3]){
    if(e[2] < e[1]){
  swap(e[2], e[1]);
        if(e[1] < e[0]) swap(e[0], e[1]);
 }
    return e[0]+e[1] > e[2];
}

inline double getArea(double e[3]){
    if(!isTriangle(e)) return -1;
    double p = sum[n]/2.0;
    return sqrt(p*(p-e[0])*(p-e[1])*(p-e[2]));
}

int main(){
    scanf("%d", &n);
    for(int i=1; i<=n; ++i){
        scanf("%d", &len[i]);
        sum[i] = sum[i-1]+len[i];
 }

    memset(f, 0, sizeof(f));
    f[0][0] = true;

    double ans = -1;
    double e[3];
 for(int i=1; i<=n; ++i){
  for(int v1=min(sum[i],sum[n]>>1); v1>=0; --v1){
   for(int v2=min(sum[i]-v1,sum[n]>>1); v2>=v1; --v2)if(v1+v2<sum[n]){
                e[0] = v1; e[1] =v2; e[2] = sum[n]-v1-v2;        
    if(v1-len[i]>= 0 && f[v1-len[i]][v2]){
                    f[v1][v2] = true;
    }
    if(!f[v1][v2] && v2-len[i]>=0 && f[v1][v2-len[i]]){
        f[v1][v2] = true;
    }
    if(f[v1][v2]){
                    ans = max(ans, getArea(e));    
    }
   }
  }
 }
    if(ans < 0) puts("-1");
 else printf("%d\n", (int)(100*ans));

    return 0;
}

 

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,