The multiplication puzzle is played with a row of cards, each containing a single positive integer. During the move player takes one card out of the row and scores the number of points equal to the product of the number on the card taken and the numbers on the cards on the left and on the right of it. It is not allowed to take out the first and the last card in the row. After the final move, only two cards are left in the row.
The goal is to take cards in such order as to minimize the total number of scored points.
For example, if cards in the row contain numbers 10 1 50 20 5, player might take a card with 1, then 20 and 50, scoring
10*1*50 + 50*20*5 + 10*50*5 = 500+5000+2500 = 8000
If he would take the cards in the opposite order, i.e. 50, then 20, then 1, the score would be
1*50*20 + 1*20*5 + 10*1*5 = 1000+100+50 = 1150.
Input
The first line of the input contains the number of cards N (3 <= N <= 100). The second line contains N integers in the range from 1 to 100, separated by spaces.
Output
Output must contain a single integer - the minimal score.
Sample Input
6
10 1 50 50 20 5
Sample Output
3650
思路:
区间dp:
当求解最优解问题时,每一步的操作都有可能在一个区间的任何部位下手,有可能用到区间dp
大体思路一般都是不断将一个区间枚举划分成若干个小区间(分法要看题意构建)再将这些小的区间按同样的方法划分
当区间缩小到一定宽度时,会发现这个区间的能枚举的操作数只有一个或没有,这时在及时赋值返回递归
一步的操作会影响下一步的操作:这时其实我们不妨去考虑枚举最后一步的操作的情况,然后再去想要想得到这最后一步的操作
我们上一步的操作应该是什么。
本题思路:
像这一题:
我们先用dp[s][t]去表示在区间s到t中的最优解
我们先去考虑:在这个大区间s-t之中枚举谁会最后一个剩下。也因为是最后一个取的,离他最近的也只有a[s]和a[t];
所以直接a[i]*a[r]*a[s]再去递归求夹在i r s 中的两区间最优解三者相加再取最小值即可。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int a[11101],dp[110][110];
int dfs(int s,int t)
{
int i;
if(dp[s][t]) return dp[s][t];
if(t-s==1) return 0;
dp[s][t]=9999999;
for(i=s+1; i<=t-1; i++)
{
dp[s][t]=min(dp[s][t],a[i]*a[s]*a[t]+dfs(s,i)+dfs(i,t));
}
return dp[s][t];
}
int main()
{
int i,j,k,m;
scanf("%d",&m);
for(i=1; i<=m; i++)
{
scanf("%d",&a[i]);
}
printf("%d",dfs(1,m));
return 0;
}