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();
        }
    }
  • 相关阅读:
    配置Podfile 一个工程内的多个Target
    iOS开发中的测试框架
    iOS 设置button文字过长而显示省略号的解决办法
    iOS界面的绘制和渲染
    iOS单元测试
    iOS消息转发机制
    对runtime的总结:让你会用Runtime
    Xcode的Refactor使用
    工厂设计模式
    iOS中的数据存储
  • 原文地址:https://www.cnblogs.com/123-123/p/5800102.html
Copyright © 2011-2022 走看看