题意:给一个序列,每次选一个数(记为b),计算左边离他最近的数(记为a),右边离他最近的数(记为c),计算a*b*c,sum+=a*b*c 重复操作直到剩下开头结尾两个数
不同的方案对应不同的sum 计算最小的sum值
分析:典型的区间dp,dp[i][j]表示把从i到j所有的数都选走得到的最小值
dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]+num[k]*num[i-1]*num[j+1]);
注:记得预处理dp[i][i],i(2~n-1)
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cstdlib> #include<cmath> using namespace std; typedef long long LL; const int INF=0x3f3f3f3f; int dp[105][105]; int a[105]; int main() { int n; while(~scanf("%d",&n)) { for(int i=1;i<=n;++i) scanf("%d",&a[i]); memset(dp,0,sizeof(dp)); for(int i=2;i<n;++i) dp[i][i]=a[i-1]*a[i]*a[i+1]; for(int l=1;l<n;++l) { for(int i=2;i+l<n;++i) { int j=i+l; dp[i][j]=INF; for(int k=i;k<=j;++k) dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]+a[k]*a[i-1]*a[j+1]); } } printf("%d ",dp[2][n-1]); } return 0; }