link
思路整理
乍一看好像没什么思路,但是不难看出每次找一个点,就会把当前区间分成两半,分开求两个区间在加上断开的代价就是整个区间的代价了
那就区间dp呗(见下图)
我们用f[L][R]表示点L,L+1,L+2....R-1,R的划分最小代价
也就是多边形(L,L+1),(L+1,L+2)...(R-1,R),(R,L)的划分代价
嗯...大概就是这样
低精代码:
#include<bits/stdc++.h>
using namespace std;
const int N=55,M=35;
int n;
int w[N],f[N][N];
int main(){
cin>>n;
for(int i=1;i<=n;i++) scanf("%d",w+i);
for(int len=3;len<=n;len++)
for(int l=1;l+len-1<=n;len++){
int r=l+len-1;
f[l][r]=2147483647;
for(int k=l+1,k<r;k++) f[l][r]=min(f[l][r],f[l][k]+f[k][r]+w[l]*w[r]*w[k]);
}
printf("%d\n",f[1][n]);
return 0;
}
高精代码
#include<bits/stdc++.h>
using namespace std;
const int N=55,M=35;
typedef long long ll;
int n;
ll w[N],f[N][N][M],temp[M];
void add(ll a[],ll b[]){
static ll c[M];
memset(c,0,sizeof(c));
for(int i=0,t=0;i<M;i++){
t+=a[i]+b[i];
c[i]=t%10;
t/=10;
}
memcpy(a,c,sizeof(c));
return;
}
void mul(ll a[],ll b){
static ll c[M];
memset(c,0,sizeof(c));
ll t=0;
for(int i=0;i<M;i++){
t+=a[i]*b;
c[i]=t%10;
t/=10;
}
memcpy(a,c,sizeof(c));
return;
}
int cmp(ll a[],ll b[]){
for(int i=M-1;i>=0;i--)
if(a[i]>b[i]) return 1;
else if(a[i]<b[i]) return -1;
return 0;
}
void print(ll a[]){
int k=M-1;
while(k&&!a[k]) k--;
while(k>=0) printf("%lld",a[k--]);
puts("");
return;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++) scanf("%lld",w+i);
ll res[M];
for(int len=3;len<=n;len++)
for(int l=1;l+len-1<=n;l++){
int r=l+len-1;
f[l][r][M-1]=1;
for(int k=l+1;k<r;k++){
memset(temp,0,sizeof(temp));
temp[0]=w[l];
mul(temp,w[k]);
mul(temp,w[r]);
add(temp,f[l][k]);
add(temp,f[k][r]);
if(cmp(f[l][r],temp)>0) memcpy(f[l][r],temp,sizeof(temp));
}
}
print(f[1][n]);
return 0;
}