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

    原题地址

    题意:

    给定一个序列,可以依次从序列中取走除了左右两端点之外的元素,每次取走一个元素,获得该元素乘以它左右两边元素乘积的点数,求可能的最小点数。

    题解:

    区间DP,首先会想到枚举区间中第一个被取走的元素k,转移dp[l][r]=min(dp[l][r],dp[l][k]+dp[k][r]+A[k]*A[k-1]*A[k+1])

    但是这个转移是失败的,因为接下来考虑dp[l][k]时,A[k-1]这个元素被取出时它的右边的元素无法确定。

    应该枚举区间中最后被取走的那个元素,转移dp[l][r]=min(dp[l][r],dp[l][k]+dp[k][r]+A[k]*A[l]*A[r])

    注意:

    k已经被取走,所以dp[l][k]不需要考虑k被取走的情况,保证了DP状态定义的一致性。

    //#include<bits/stdc++.h>
    #include <stdio.h>
    #include <algorithm>
    #include <string.h>
    #define clr(x,y) memset((x),(y),sizeof(x))
    
    using namespace std;
    typedef long long LL;
    
    const int maxn=100;
    const int inf=2e8;
    
    int dp[maxn+5][maxn+5];
    int A[maxn+5];
    int n;
    
    int DP(int l,int r)
    {
        if (dp[l][r]!=-1) return dp[l][r];
        if (l==r-1) return dp[l][r]=0;
    
        dp[l][r]=inf;
        for (int i=l+1;i<=r-1;++i)
        {
            dp[l][r]=min(dp[l][r],DP(l,i)+DP(i,r)+A[i]*A[l]*A[r]);
        }
    
        //printf("%d %d %d
    ",l,r,dp[l][r]);
        return dp[l][r];
    }
    
    void solve()
    {
        clr(dp,-1);
        printf("%d
    ",DP(1,n));
    }
    
    int main(void)
    {
        #ifdef ex
        freopen ("../in.txt","r",stdin);
        //freopen ("../out.txt","w",stdout);
        #endif
    
        while (scanf("%d",&n)==1)
        {
            for (int i=1;i<=n;++i)
            {
                scanf("%d",&A[i]);
            }
            solve();
        }
    }
  • 相关阅读:
    DB2数据库BACKUP PENDING状态(修改日志模式导致)(转)
    JAVA调用WebService实例
    eclipse启动报JVM terminated. Exit code=-1的解决方法
    JAVA使用Dom4j组装、解析XML
    任务调度IBM Tivoli Workload Scheduler(TWS)
    Java遍历Map数据的几种方式
    谈谈我对Log4j2以外的感想
    ESQL中添加JMS参数
    node.js-node-inspector调试
    前端-浏览器内核
  • 原文地址:https://www.cnblogs.com/123-123/p/5800102.html
Copyright © 2011-2022 走看看