tyvj1014

题目链接:https://www.tyvj.cn/Problem_Show.aspx?id=1014

背景 Background
太原成成中学第2次模拟赛 第四道
描述 Description
乘法游戏是在一行牌上进行的。每一张牌包括了一个正整数。在每一个移动中,玩家拿出一张牌,得分是用它的数字乘以它左边和右边的数,所以不允许拿第1张和最后1张牌。最后一次移动后,这里只剩下两张牌。
  你的目标是使得分的和最小。
  例如,如果数是10 1 50 20 5,依次拿1、20、50,总分是           10*1*50+50*20*5+10*50*5=8000
  而拿50、20、1,总分是1*50*20+1*20*5+10*1*5=1150。
输入格式 Input Format
输入文件mul.in的第一行包括牌数(3<=n<=100),第二行包括N个1-100的整数,用空格分开。
输出格式 Output Format
输出文件mul.out只有一个数字:最小得分
样例输入 Sample Input

样例输出 Sample Output

时间限制 Time Limitation
各个测试点1s

[分析]

记忆化搜索DP

f[i][j]表示区间[i,j]所得到的最小值。F[I,J]:=MIN(F[I,K]+F[K,J]+A[I]*A[K]*A[J])其中I<K<J。(K表示区间[i,j]最后一次取第K张牌)

不断地划分区间,把结果保存起来。

#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
long long int f[101][101];int a[101], i, j, n, INF=0x7f7f7f7f;
void dfs(int l, int r) {
    if(r-l<=1) {f[l][r]=0; return;} if(f[l][r]!=INF) return;
    for(int i=l+1;i<=r-1;++i) dfs(1,i),dfs(i,r),f[l][r]=min(f[l][r],f[l][i]+f[i][r]+a[i]*a[l]*a[r]);
}
int main(void) {
    freopen("in1.txt","r",stdin);
    scanf("%d",&n);for(i=1;i<=n;scanf("%d",a+i++))
        ;for(i=0;i<=n;++i)for(j=0;j<=n;++j)f[i][j]=INF;dfs(1,n);printf("%lld
",f[1][n]);
    return 0;
}

或者:

 1 var
 2  i,j,k,l,n:longint; 
 3  f:array[1..100,1..100]of longint;
 4  num:array[1..100]of longint;
 5 
 6 
 7 begin
 8   readln(n);
 9   for i:=1 to n do
10    read(num[i]);
11 
12     for l:=1 to n do
13       for i:=1 to n-l+1 do
14         begin
15           j:=i+l+1;
16           f[i,j]:=MaxLongint;
17           for k:=i+1 to j-1 do
18             if f[i,k]+f[k,j]+num[i]*num[k]*num[j]<f[i,j] then
19               f[i,j]:=f[i,k]+f[k,j]+num[i]*num[k]*num[j];
20         end;
21         
22   writeln(f[1,n]);
23   
24 end.
原文地址:https://www.cnblogs.com/nbalive2001/p/4053989.html