题意:给出一串数字,第一个和最后一个数字不能抽取,每一次抽取一个数字得到的价值为这个数字和相邻两个数字的乘积,问把整个序列最后只剩下第一个和最后一个数字时的最小价值。
思路:区间DP经典题,我们令dp[i][j]为第i到第j个数字去光后的价值,转移方程dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+a[i]*a[j]*a[k])
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <set>
#include <ctime>
#include <cmath>
#include <cctype>
using namespace std;
#define maxn 100000
#define LL long long
int cas=1,T;
int dp[105][105];
int a[105];
int main()
{
int n;
while (scanf("%d",&n)!=EOF)
{
for (int i = 0;i<n;i++)
scanf("%d",&a[i]);
for (int i = 0;i<n-2;i++)
dp[i][i+2]=a[i]*a[i+1]*a[i+2];
int len;
for (len=3;len<n;len++)
{
for (int i = 0;i+len<n;i++)
{
int j = len+i;
for (int k = i+1;k<j;k++)
{
if (dp[i][j]==0)
dp[i][j]=dp[i][k]+dp[k][j]+a[i]*a[j]*a[k];
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+a[i]*a[k]*a[j]);
}
}
}
printf("%d\n",dp[0][n-1]);
}
//freopen("in","r",stdin);
//scanf("%d",&T);
//printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
return 0;
}