程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> poj 1948 Triangular Pastures (dp二維背包)

poj 1948 Triangular Pastures (dp二維背包)

編輯:C++入門知識

 


題目大意:

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

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved