乘法游戏
背景 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。
输入格式 InputFormat
输入文件的第一行包括牌数(3<=n<=100),第二行包括N个1-100的整数,用空格分开。
输出格式 OutputFormat
输出文件只有一个数字:最小得分
样例输入 SampleInput [复制数据]
6
10 1 50 50 20 5
样例输出 SampleOutput [复制数据]
3650
由于在做这道题的时候没有学区间动归,硬是想不出办法。
在大神的指教下,终于···· = =
状态f[i][j]表示i到j的最优解
注意要先循环区间长度k,否则搞不清拓扑关系
状态转移方程f[i][i+k]=max(f[i][j],f[j+1][i+k]);(i
#include
int p[1200],f[1200][1200];
int min(int x,int y)
{
if(x==y)
return p[x-1]*p[x]*p[x+1];
int i,k,j,m;
if(0+f[x+1][y]+p[x-1]*p[x]*p[y+1]<0+f[x][y-1]+p[x-1]*p[y]*p[y+1])
m=f[x+1][y]+p[x-1]*p[x]*p[y+1];
else m=f[x][y-1]+p[x-1]*p[y]*p[y+1];
for(k=x+1;k<=y-1;k++)
{
if(m>f[x][k-1]+f[k+1][y]+p[x-1]*p[k]*p[y+1])
m=f[x][k-1]+f[k+1][y]+p[x-1]*p[k]*p[y+1];
}
return m;
}
int main()
{
int n,i,k,j;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&p[i]);
for(k=0;k<=n-3;k++)
for(i=2;i<=n-k-1;i++)
f[i][i+k]=min(i,i+k);
printf("%d\n",f[2][n-1]);
}