乘法游戏

P1014 乘法游戏
时间: 1000ms / 空间: 131072KiB / Java类名: Main

背景

太原成成中学第2次模拟赛 第四道

描述

乘法游戏是在一行牌上进行的。每一张牌包括了一个正整数。在每一个移动中,玩家拿出一张牌,得分是用它的数字乘以它左边和右边的数,所以不允许拿第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。 

输入格式

输入文件的第一行包括牌数(3<=n<=100),第二行包括N个1-100的整数,用空格分开。

输出格式

输出文件只有一个数字:最小得分

测试样例1

输入


10 1 50 50 20 5

输出

3650
 

 
记忆化搜索:dp(x,y)指的是从x到y(不包括x,y),这一段中,中间的值,所以如果x+1>=y就是0(想像一下就2张牌的时候),
dp(x+1,i)+dp(i,y)+a[x]*a[i]*a[y]的意思是先计算了左边(x到i中间的一段),然后计算了右边(i到y中间一段),最后加上取出i的,比如5张牌,i=3,把2(左边)和4(右边)取了,再取中间的3(中间)。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define inf 1000000000
using namespace std;
int n,a[105],f[105][105];
int dp(int l,int r)
{
    if(l+1==r)return 0;
    if(f[l][r]<inf)return f[l][r];
    for(int i=l+1;i<r;i++)
        f[l][r]=min(f[l][r],dp(l,i)+dp(i,r)+a[l]*a[i]*a[r]);
    return f[l][r];
}
int main()
{
    memset(f,127,sizeof(f));
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    printf("%d\n",dp(1,n));        
    return 0;    
}
View Code

 

posted @ 2016-08-17 17:50  pandaB  阅读(719)  评论(0编辑  收藏  举报