1. 程式人生 > >code vs 1966 乘法遊戲

code vs 1966 乘法遊戲

1966 乘法遊戲

 時間限制: 1 s  空間限制: 128000 KB  題目等級 : 黃金 Gold 題目描述 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 Description

輸入檔案的第一行包括牌數(3<=n<=100),第二行包括N個1-100的整數,用空格分開。 

輸出描述 Output Description

 輸出檔案只有一個數字:最小得分

樣例輸入 Sample Input

6
10 1 50 50 20 5

樣例輸出 Sample Output

3650

此題屬於區間dp,第一眼看感覺跟石子合併有點像,於是就按照那種方式編寫。但是除錯的過程中發現會出現負值,應該是資料超範圍了,所以發現考慮不周。經大神指點發現沒有特殊處理f[i][i+1]的情況,相鄰兩個無法運算所以很顯然應該是0,但是如果不初始化就會是最大值,那麼很顯然會錯。但是貌似還是不對,於是發現題意理解有誤。唉,於是重新寫,就寫成了這個樣子。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int i,j,k,n,m;
int num[110],f[110][110];
using namespace std;
int main()
{
	scanf("%d",&n);
	memset(f,127/3,sizeof(f));
	for (i=1;i<=n;i++)
	 {
	  scanf("%d",&num[i]);
	  f[i][i]=num[i];
     }
    for (i=1;i<=n-1;i++)
     f[i][i+1]=0;
	for (i=2;i<=n;i++)
	 {
	    for (j=1;j<=n-i+1;j++)
	     {
	     	for (k=j+1;k<=i+j-2;k++)
	     	 f[j][i+j-1]=min(f[j][i+j-1],f[j][k]+f[k][i+j-1]+num[j]*num[k]*num[i+j-1]);
	     }
	 }
    /*for (i=1;i<=n-1;i++)
     {
     	for (j=i;j<=n;j++)
     	 printf("%d ",f[i][j]);
     	printf("\n");
     }*/
    printf("%d",f[1][n]);
	return 0;
}