1. 程式人生 > >動態規劃——Poj 1651 Multiplication Puzzle

動態規劃——Poj 1651 Multiplication Puzzle

1)   題目


Multiplication Puzzle

Time Limit: 1000MS

Memory Limit: 65536K

Total Submissions: 4948

Accepted: 2958

Description

The multiplication puzzle is played with arow of cards, each containing a single positive integer. During the move playertakes one card out of the row and scores the number of points equal to theproduct of the number on the card taken and the numbers on the cards on theleft and on the right of it. It is not allowed to take out the first and thelast card in the row. After the final move, only two cards are left in the row. 

The goal is to take cards in such order as to minimize the total number ofscored points. 

For example, if cards in the row contain numbers 10 1 50 20 5, player mighttake a card with 1, then 20 and 50, scoring 

10*1*50 + 50*20*5 + 10*50*5 = 500+5000+2500 =8000


If he would take the cards in the opposite order, i.e. 50, then 20, then 1, thescore would be 

1*50*20 + 1*20*5 + 10*1*5 = 1000+100+50 =1150.

Input

The first line of the input contains thenumber of cards N (3 <= N <= 100). The secondline contains N integers in the range from 1 to 100, separated by spaces.

Output

Output must contain a single integer - theminimal score.

Sample Input

6

10 1 50 50 20 5

Sample Output

3650

2)    題意

有N張寫有數字的卡片排成一行,按一定次序從中拿走N-2張(第1張和最後一張不能拿),每次只拿一張,取走一張卡片的同時,會得到一個分數,分值的計算方法是:要拿的卡片,和它左右兩邊的卡片,這三張卡片上數字的乘積。按不同的順序取走N-2張卡片,得到的總分可能不相同,求出給定一組卡片按上述規則拿取的最小得分。

3)    資料範圍

卡片的數量N(3<= N <= 100),卡片上的數字M(1<= M <= 100)。

給定的一組卡片,不同的拿取方法總共有(N-2)!種。列舉法不可行。

當N = 100,所有卡片上的數字都等於100時,得到的總分數T為:

T = (N-2) * (100 * 100 * 100) = 98000000

所以4位元組整形即可儲存。

4)    演算法

這道題實質上就是矩陣連乘,所以可以使用動態規劃法,或者備忘錄法。

5)    程式碼

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

#define SIZE 105
#define INF 999999999

int cards[SIZE];
int d[SIZE][SIZE];

int MinScore(int n)
{
	memset(d, 0, sizeof(d));

	int len;
	for (len = 1; len < n; len++)
	{
		int i, j, k;
		for (i = 1, j = len+1; j < n; i++, j++)
		{
			int min = INF;
			for (k = i; k < j; k++)
			{
				int count = d[i][k] + d[k+1][j] + cards[i-1]*cards[k]*cards[j];
				if (count < min)
				{
					min = count;
				}
			}
			d[i][j] = min;
		}
	}
	return d[1][n-1];
}

int main(void)
{
	int ncards;
	while (scanf("%d", &ncards) != EOF)
	{
		int i;
		for (i = 0; i < ncards; i++)
		{
			scanf("%d", &cards[i]);
		}

		printf("%d\n", MinScore(ncards));
	}
	return 0;
}

6)    測試資料

6
10 1 50 50 20 5

7

30 35 15 5 10 20 25

3

1 2 3

100

100 100 100 100 100 100 100 100 100 100

100 100 100 100 100 100 100 100 100 100

100 100 100 100 100 100 100 100 100 100

100 100 100 100 100 100 100 100 100 100

100 100 100 100 100 100 100 100 100 100

100 100 100 100 100 100 100 100 100 100

100 100 100 100 100 100 100 100 100 100

100 100 100 100 100 100 100 100 100 100

100 100 100 100 100 100 100 100 100 100

100 100 100 100 100 100 100 100 100 100

7)    提交結果