zoukankan      html  css  js  c++  java
  • POJ-1651 Multiplication Puzzle 区间DP

    题目链接:https://vjudge.net/problem/POJ-1651

    题意:

    题目的意思是给定一个数列,每次取出其中一个数字,价值增加这个数字与其左右两个数字的乘积,直到最后只剩两个数字,求价值的最小值。

    分析:

    首先这种一步步求最优解的问题,可以想到会不会是贪心问题?假设贪心可以解决,那么可以想到的策略就是每一步取使得增加价值最小的数字。但是事实是这种策略不是总正确的。反例如下:

            数列为{ 10 1 50 50 20 5 },则按照这种策略得到的价值为

    10*1*50 + 50*20*5 + 50*50*5 + 10*50*5 = 20500

            但是事实上,最优策略得到的最小价值为3650。故此题不是贪心问题,应该考虑区间DP。

    为什么会想到区间DP呢,因为这是分步求解最优问题,每一步的求解对结果都会产生影响,而且根据上面贪心的验证,我们知道这不是一个贪心问题,所以应该就是区间DP问题无疑了。

    应用区间DP的思路就是,求出每一段区间的价值最小值,逐渐增大范围扩散至整个区间。

    代码如下:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #define inf 0x3fffffff
    const int maxn = 550;
    using namespace std;
    int arr[maxn];
    int dp[maxn][maxn];
    int n;
    
    void DP() {
        for(int cnt = 3; cnt <= n; cnt++) {
            for(int i = 0; i < n-2; i++) {
                int j = i+cnt-1;
                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]+arr[i]*arr[k]*arr[j]);
                }
            }
        }
    }
    
    int main(void) {
        while(scanf("%d", &n) == 1) {
            for(int i = 0; i < n; i++) {
                scanf("%d", &arr[i]);
            }
            DP();
            printf("%d
    ", dp[0][n-1]);
        }
    }
  • 相关阅读:
    Spring学习02——控制反转、依赖注入
    Spring学习01——HelloSpring
    $(function() {})和$(document).ready(function(){ })
    tomcat 学习
    XML学习
    使用git提交项目至github的标准步骤
    Bootstrap快速入门
    HashMap底层原理及面试问题 [更新中]
    ArrayList remove()元素遇到的问题
    linux 给指定用户分配文件夹权限
  • 原文地址:https://www.cnblogs.com/RB26DETT/p/10763158.html
Copyright © 2011-2022 走看看