1. 程式人生 > >計蒜客 213 乘法遊戲

計蒜客 213 乘法遊戲

乘法遊戲

通過率: 8.33% 時間限制: 1000ms 記憶體限制: 65536K

關鍵詞: 區間DP

Description

乘法遊戲是在一行牌上進行的。每一張牌包括了一個正整數。在每一個移動中,玩家拿出一張牌,得分是用它的數字乘以它左邊和右邊的數,所以不允許拿第1張和最後1張牌。最後一次移動後,這裡只剩下兩張牌。你的目標是使得分的和最小。

例如,如果數是10 1 50 20 5,依次拿1、20、50
總分是 10150+50205+10505=8000

而拿50、20、1,總分是15020+1205+1015=1150。

Input

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

Output

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

SampleInput

6
10 1 50 50 20 5

SampleOutput

3650

Analyze

區間DP:

dp[i][j]表示區間[i,j]的最小值.

在 [i, j] 區間中:

  • dp[i][k] 算出 (i, k) 區間中的最小值,最後剩下 a[i], a[k]
  • dp[k][j] 算出 (k, j) 區間中的最小值,最後剩下 a[k], a[j]
  • 最後在 [i, j] 區間中就只剩下 dp[i][k], dp[k][j] 以及 a[i], a[k], a[j],

dp[i][j] = dp[i][k] + dp[k][j] + a[i]*a[k]*a[j] (i < k < j)

由於K是(i, j)內的任意值。所以:

dp[i][j] = min(dp[i][k]+dp[k][j]+a[i]*a[k]*a[j], dp[i][j]);

Code

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<stdlib.h>
#include<algorithm>
#include <limits.h>
using namespace std;

int dp[110][110];
int
arr[110]; const int INF=2147483647; //2147483647 int main() { int n; // freopen("E:\\in.txt", "r", stdin);//輸入重定向,輸入資料將從in.txt檔案中讀取 // freopen("E:\\out2.txt", "w", stdout);//輸出重定向,輸出資料將儲存在out.txt檔案中 while(scanf("%d",&n)!=EOF) { for(int i=0; i<n; i++) scanf("%d",&arr[i]); for(int i=0; i<n-1; i++)//當[i,j]區間長度為3的時候我們需要相鄰的dp[i][j]==0(j-i==1) dp[i][i+1] = 0; for(int len=3; len<=n; len++) //區間長度(最小3,最大n) { for(int i=0; i<n-2; i++) //列舉區間起點 { int j=i+len-1; //區間終點(3<=j<=n+n-1) if(j >= n) break; //我們最多算dp[0, n-1] dp[i][j] = INF; for(int k=i+1; k<j; k++) dp[i][j]=min(dp[i][k]+dp[k][j]+arr[i]*arr[k]*arr[j],dp[i][j]); } } printf("%d\n",dp[0][n-1]); } return 0; }