题目链接
区间dp练习题,不过这题除了区间dp外…还有高精度的问题,先放一放…不用高精度的话在oj上面只能拿50分.
因为写区间dp我都习惯了写记忆化搜索.可能会不太好…毕竟可能会爆栈.速度也相对慢一点.
思路分析:由于是自顶向下的方法,所以我一般都先从最终状态出发,来把主框架先写好.最终状态是由一个一个的小三角形所组成的,区间范围是[1,n].那么在大区间之中选一个点和大区间的头尾组成一个三角形,就可以分割出两个小区间.分别是[1,k][k,n],合并区间的代价就是三个点的权值乘起来.画个图可能会比较清晰,我比较懒就不贴图了.这是主框架的划分方法.现在来考虑一下细节.
所谓的细节也就是递归的边界.什么时候结束划分呢.就是组成一个三角形需要三个点.如果一个区间长度小于等于2的时候.就return 0就好了.代码实现上面就是j-i == 1.
至于高精度嘛…有时间再补充.
#define LL long long
#include <iostream>
#include <string.h>
#include <algorithm>
#include <cmath>
using namespace std;
const LL INF = pow(2,62)-1;
const int N = 50+10;
LL a[N];
LL dp[N][N];
LL dfs(int i,int j){
if(j-i<=1) return dp[i][j] = 0;
if(dp[i][j] != INF) return dp[i][j];
LL sum = a[i]*a[j];
for(int k=i+1;k<j;++k){
dp[i][j] = min(dp[i][j],dfs(i,k)+dfs(k,j)+sum*a[k]);
}
return dp[i][j];
}
int main(){
int n;
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){
dp[i][j] = INF;
}
}
cout << dfs(1,n) << endl;
return 0;
}