题意:有一行n个数,需要从中取数,每次取数获得的权值为该数与左右相邻数的乘积,最左边和最右边的数不能被取到,求最小的权值之和。
分析:区间DP的典型题,可以用dp[i][j]表示第i个数和第j个数不取的时候,区间[i,j]的最小值
那么用k枚举所有的间断点表示上一个状态 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+a[i]*a[k]*a[j]);
代码如下:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; #define INF 0x3f3f3f3f int n; int dp[110][110]; int a[110]; int minn; int main() { while(scanf("%d",&n)!=EOF) { minn=INF; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { if(j-i==1) dp[i][j]=0; else dp[i][j]=INF; } for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int l=2;l<n;l++) for(int i=1;i<=n-l;i++) { int j=i+l; for(int k=i+1;k<j;k++) dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+a[i]*a[k]*a[j]); } printf("%d ",dp[1][n]); } return 0; }