:この問題を行う前に、あなたは最初の三角形の面積の公式を理解すべきであるヘレン式を。
ここで、三角形の任意の3辺のために、即ち、書き込みを書き込む結論\(A、B、C \) 、そう\(X = \ tfrac {1} {2}(A + B + C)\) 、そこである\ (S = \ SQRT {X(XA)、(XB)、(XC)} \) 。
我々は次に、我々は、セット状態を考える\(F [k]は[A ] [B] [C] \)は前者を表す(K \)\長の三方を囲まれたかどうかを目木材\(A、B、C \)三角形。しかし、辺の長さが最大であることができ(800 \)\、時間と空間の複雑さ(800 ^ 3 \タイムズ40 \)\、それは明らかに現実的ではありません。
我々は最適化しようとして、三角形の周囲長が一定であることを観察し、その後、決定する2つの側面が第3の辺を見つけることができます。セット\(C \)三角形の周囲長であり、我々が作る\(F [k]は[A ] [B]が\) 前者を表す\(K \)の長さの囲まれた三方か番目木材\(A、 B、キャブ\)三角形。
転送分割3例:
-
セクション\(K \)上の第木材\(I \)この側面:
次いで、使用前に\(K-1 \)長さの辺を搭乗番目\(IA [k]を\)と\(J \)三角形、すなわち\(F [K-1] [IA [K] [J] \)
-
セクション\(K \)に番目木材\(J \)この側部:\(F [1-K] [I] [JA [K] \)
-
セクション\(K \)第三の側面に第木材:\(F [1-K] [I]、[J] \)
伝達方程式があります。
この時点で私たちを見つけるのは簡単で、ときにのみ転送、最適化スペースに続け\(F [K-1] [] [] \) 私たちは、一次元を取り除くので、関連は、元のデータと配列の現在値の更新を検討(F [\ I] [J] \)。
このことに留意すべきである\(I、J \)サイクルを落ちなければならない、我々がいることを確認したいので(F [i]が[JA \ [] K] \)をし、\(F [JA [] k個 ] \ [i])と値であるが床の上、および\(01 \)と同様のバックパック。
最後に、のために(F [I] [J \ ] = 1 \) \(I、J \) 、我々は決定((I、J、Cijの\ )\) 組成三角形かどうか。組成物は、ヘレンエリア更新式の答えを計算するために使用された場合。
\(\ operatorname {コード:} \)
#include<bits/stdc++.h>
using namespace std;
const int N=45;
int n,sum,ans=-1,a[N],f[805][805];
bool check(int x,int y,int z) {
if(x && y && z && x+y>z && y+z>x && x+z>y) return true;
return false;
}
int hailen(double x,double y,double z) {
double s=(x+y+z)/2;
return sqrt(s*(s-x)*(s-y)*(s-z))*100;
}
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum=sum+a[i];
f[0][0]=1;
for(int k=1;k<=n;k++) {
for(int i=(sum>>1);i>=0;i--) {
for(int j=(sum>>1);j>=0;j--) {
if(i-a[k]>=0 && f[i-a[k]][j]) f[i][j]=1;
if(j-a[k]>=0 && f[i][j-a[k]]) f[i][j]=1;
}
}
}
for(int i=0;i<=(sum>>1);i++) {
for(int j=0;j<=(sum>>1);j++) {
if(f[i][j] && check(i,j,sum-i-j)) ans=max(ans,hailen(i,j,sum-i-j));
}
}
printf("%d\n",ans);
return 0;
}