码迷,mamicode.com
首页 > 其他好文 > 详细

Multiplication Puzzle

时间:2020-01-29 16:01:52      阅读:70      评论:0      收藏:0      [点我收藏+]

标签:最优   第一个   integer   ios   tip   oppo   lin   mem   ++   

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, 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, the score would be 

1*50*20 + 1*20*5 + 10*1*5 = 1000+100+50 = 1150.
Input 
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
Output must contain a single integer - the minimal score.
example
input
6
10 1 50 50 20 5
output
3650
大意就是输入一堆数字每个数与自己左右的数相乘然后这个数就作废(相当于剔除)接着操作,最后把这些数加在一起和最小,因此第一个和最后一个就不能进行这些操作
所以会想到用动态规划进行操作,每一次进行比较,选出更小的那个数值
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;

const int maxn = 105;
const int inf = 0x3f3f3f3f;

int main()
{
    int n;
    int num[maxn];
    int dp[maxn][maxn];
    while (scanf("%d", &n) != EOF)
    {
        memset(dp, 0, sizeof(dp));
        for (int i = 1; i <= n; ++i) 
        {
            cin >> num[i];
        }
        for (int m = 2; m <= n - 1; m++)
        {
            for (int i = 1; i + m <= n; i++)
            {
                int j = i + m;
                dp[i][j] = inf;
                for (int k = i + 1; k < j; k++)
                {
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + num[i] * num[j] * num[k]);//对最小值进行判断
                }
            }
        }
        cout << dp[1][n] << endl;
    }
    return 0;
}

递推式是 DP 的核心,得到递推式也就基本得到了 DP 的代码。DP 问题的特征是最优子结构,即问题包含多个子问题,问题的最优解中包含子问题的最优解。求解过程中相同的子问题可能多次被遇到,把已经求出答案的子问题的解记录到表中,这样问题的复杂度通常从指数降低到多项式。(1)规模最小的子问题最容易,是三个数字,结果是三个数字的乘积。

  (2)为了把问题分解成规模更小的子问题,定义问题如下,给出一个整数数组 num[ ],求索引从 i 到 j 范围的一串卡片操作到最后得到的最小结果是 dp[i][j],问题规模是卡片数,即 j - i - 1;

(3)类似矩阵乘法,现在把 s[i][j] 从中间某个位置(i < k < j)分裂成规模更小的两个子问题,即是把数字串的长度减小:

num[i], ..., num[k], ...,num[j]; ( c[k] 是最后取走的牌 )

先把 num[i] , ... , num[k] 中间的所有数字取走,根据问题定义得到结果是 dp[i][k]; 剩下的是 num[i], num[k], ..., num[j];

再把num[k], ... , num[j] 中间的所有数字取走,根据问题定义得到结果是dp[k][j]; 剩下的是 num[i], num[k], num[j];

最后取走 num[k];因此如果最后取走 k ,则 dp[i][j] = dp[i][k] + dp[k][j] + num[i]*num[k]*num[j]; 

 

 

Multiplication Puzzle

标签:最优   第一个   integer   ios   tip   oppo   lin   mem   ++   

原文地址:https://www.cnblogs.com/-113/p/12240403.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!