區間DP——凸多邊形的三角形劃分
阿新 • • 發佈:2019-02-08
問題 C: 凸多邊形的三角形劃分
時間限制: 1 Sec 記憶體限制: 128 MB
提交: 4 解決: 2
[提交][狀態][討論版][命題人:add_oopscyc]
題目描述
給定一具有N個頂點(從1到N編號)的凸多邊形,每個頂點的權均已知。問如何把這個凸多邊形劃分成N-2個互不相交的三角形,使得這些三角形頂點的權的乘積之和最小?
輸入
第一行 頂點數N(N<50)。
第二行 N個頂點(從1到N)的權值,權值為小於32768的整數。
輸出
各三角形頂點的權的乘積之和最小值。
樣例輸入
5 121 122 123 245 231
樣例輸出
12214884
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<queue> using namespace std; int n,j; long long int f[110][110][110],a[110],s1[110],s2[110],s3[110]; void mark(long long int c[])//高精度處理 { for(int i=1;i<=c[0];i++) { c[i+1]+=c[i]/10000; c[i]%=10000; } while(c[c[0]+1]) { c[0]++; c[c[0]+1]+=c[c[0]]/10000; c[c[0]]%=10000; } } void mul(long long int a1,long long int a2,long long int a3,long long int c[]) //將a1*a2*a3的值儲存在陣列c中,高精度乘法 { c[0]=c[1]=1; for(int i=1;i<=c[0];i++) c[i]*=a1; mark(c); for(int i=1;i<=c[0];i++) c[i]*=a2; mark(c); for(int i=1;i<=c[0];i++) c[i]*=a3; mark(c); } void add(long long int a[],long long int b[],long long int c[]) //高精度加法 { c[0]=max(a[0],b[0]); for(int i=1;i<=c[0];i++) c[i]=a[i]+b[i]; mark(c); } int compare(long long int a[],long long int b[]) { if(a[0]<b[0]) return 0; if(a[0]>b[0]) return 1; for(int i=a[0];i>=1;i--) if(a[i]<b[i])return 0; else if(a[i]>b[i])return 1; return 0; } void print()//輸出答案 { cout<<f[1][n][f[1][n][0]]; for(int i=f[1][n][0]-1;i>=1;i--) { cout<<f[1][n][i]/1000; cout<<f[1][n][i]/100%10; cout<<f[1][n][i]/10%10; cout<<f[1][n][i]%10; } cout<<endl; } int main() { cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f[i][j][0]=0;//初始化 for(int num=2;num<=n-1;num++)//劃分次數 for(int i=1;i<=n-num;i++)//起點 { j=i+num;//終點 f[i][j][0]=60; for(int k=i+1;k<=j-1;k++) { memset(s1,0,sizeof(s1)); memset(s2,0,sizeof(s2)); memset(s3,0,sizeof(s3)); mul(a[i],a[k],a[j],s1);//將三角形頂點權值相乘,s1=a[i]*a[k]*a[j] add(f[i][k],f[k][j],s2);//s2=f[i][k]+f[k][j] add(s1,s2,s3);//s3=s1+s2=a[i]*a[k]*a[j]+f[i][k]+f[k][j] if(compare(f[i][j],s3)) memcpy(f[i][j],s3,sizeof(s3));//f[i][j]=min(f[i][j],s3),求最小值 } } print();//輸出答案 return 0; }