- 总时间限制:
- 1000ms 内存限制:
- 65536kB
- 描述
- The multiplication puzzle is played with a row of cards, each containing a single positive integer. During the move player takes one card out of the row and scores the number of points equal to the product of the number on the card taken and the numbers on the cards on the left and on the right of it. It is not allowed to take out the first and the last 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 of scored points.
For example, if cards in the row contain numbers 10 1 50 20 5, player might take a card with 1, then 20 and 50, scoring10*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, the score would be1*50*20 + 1*20*5 + 10*1*5 = 1000+100+50 = 1150. 输入 - The first line of the input contains the number of cards N (3 <= N <= 100). The second line contains N integers in the range from 1 to 100, separated by spaces. 输出
- Output must contain a single integer - the minimal score. 样例输入
-
6 10 1 50 50 20 5
样例输出 -
3650
#include <iostream> #include <cstring> using namespace std; int N = 0; int v[0x100]; int result[0x100][0x100]; int getscore ( int start, int end ){ //返回start到end区间的最小值 if (start + 2 > end ) return 0; if (result[start][end] != -1 ) return result[start][end]; else { for ( int i = start + 1; i< end; i++){ int tmp = v[i] * v[start] * v[end] + getscore( start , i) + getscore ( i, end ); if ( tmp < result[start][end] || result[start][end] == -1 ){ result[start][end] = tmp; } } return result[start][end]; } } int main(){ memset(result,-1,sizeof(result)); cin >> N; for (int i = 1; i <= N ;i++){ cin >> v[i]; } cout << getscore( 1, N ); }
解题思路:
运用递归的思路来解这道题
先考虑边界情况,即只剩三个数的时候,结果是固定的,即v[1]*v[i]*v[N],N为数据的个数。
我们假设f(a,b)可以返回区间内所有取法的minscore,便得到了递推式:
f(i,N)= min( f(1,i)+f(i,N)+i*f(1)*f(N) ); i取区间(1,N)的任意整数;
当a+2>b时,f(a,b) = 0 (另一个边界条件)。
同时使用记忆化搜索的策略,如果result存在直接调用,否则计算以后再行调用。