Multiplication Puzzle
题意&分析:
给定一个数列,出去第一个和最后一个数,中间的数都可以取,再左边和右边各取一个数,三者相乘,即m[ i ]* m[ k ] * m [ j ] (1 <= i < k < j <= n ) ; 求最小的和。
这道题类似矩阵连乘的问题(传送门)。
dp[ i ][ j ] 的含义是在区间[ i - 1, j ] 的区间内最小的乘法和。这里和一般的区间dp模板稍有区别,不过写法很随意,都可以。
代码如下:
#define INF 0x3f3f3f3f
#define TEST cout<<"stop here"<<endl
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
int dp[110][110];
int a[110];
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int n;
while(cin>>n){
memset(dp,0,sizeof(dp));
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++){
cin>>a[i];
}//第一种写法
for(int i=n-1;i>=2;i--){
for(int j=i+1;j<=n;j++){
dp[i][j] = INF;
for(int k=i;k<j;k++){
dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]+a[i-1]*a[j]*a[k]);
}
}
}//第二种写法
/*
for(int d=2;d<n;d++){
for(int i=2;i+d<=n + 1;i++){
int j = i + d - 1;
dp[i][j] = INF;
for(int k=i;k<j;k++){
dp[i][j] = min(dp[i][j],dp[i][k] + dp[k+1][j] + a[i-1]*a[k]*a[j]);
}
}
}*/
cout<< dp[2][n] <<endl;
}
return 0;
}
参考资料: