• POJ 1651 Multiplication Puzzle (区间DP,经典)


    题意:

      给出一个序列,共n个正整数,要求将区间[2,n-1]全部删去,只剩下a[1]和a[n],也就是一共需要删除n-2个数字,但是每次只能删除一个数字,且会获得该数字与其旁边两个数字的积的分数,问最少可以获得多少分数?

    思路:

      类似于矩阵连乘的问题,用区间DP来做。

      假设已知区间[i,k-1]和[k+1,j]各自完成删除所获得的最少分数,那么a[k]是区间a[i,j]内唯一剩下的一个数,那么删除该数字就会获得a[k]*a[i-1]*a[i+1]的分数了。在枚举k的时候要保证[i,j]的任一子区间都已经完成了计算。

     1 //#include <bits/stdc++.h>
     2 #include <iostream>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <map>
     7 #include <algorithm>
     8 #include <vector>
     9 #include <iostream>
    10 #define pii pair<int,int>
    11 #define INF 0x7f7f7f7f
    12 #define LL unsigned long long
    13 using namespace std;
    14 const double PI  = acos(-1.0);
    15 const int N=110;
    16 
    17 int a[N];
    18 LL dp[N][N];
    19 
    20 int cal(int n)
    21 {
    22     memset(dp, 0, sizeof(dp));
    23     for(int i=1; i<=n; i++)
    24     for(int j=i; j<=n; j++)
    25         dp[i][j]=INF;
    26 
    27     for(int j=2; j<n; j++)
    28     for(int i=j; i>1; i--)
    29     for(int k=i; k<=j; k++)     //枚举区间a[i->j]最后剩下的数字是a[k]
    30         dp[i][j]=min(dp[i][j], dp[i][k-1]+dp[k+1][j]+a[k]*a[i-1]*a[j+1]);
    31 
    32     return dp[2][n-1];
    33 }
    34 
    35 
    36 int main()
    37 {
    38     freopen("input.txt", "r", stdin);
    39     int n;
    40     while(~scanf("%d",&n))
    41     {
    42         for(int i=1; i<=n; i++)    scanf("%d",&a[i]);
    43         printf("%d
    ", cal(n));
    44     }
    45     return 0;
    46 
    47 }
    AC代码
  • 相关阅读:
    有了bootstrap,为什么还要做amaze ui
    互联网科普知识【野狗】
    诶,很有意思的点子——云适配
    nodeJS一些事儿
    主流浏览器js 引擎内核市场份额attialx总结vOa9
    50 个 Bootstrap 插件
    Bean Validation
    Spring Security的核心拦截器
    关于未来十年企业架构的十个关键词
    写一个函数对字符串数组排序,使所有变位词都相邻
  • 原文地址:https://www.cnblogs.com/xcw0754/p/4847377.html
Copyright © 2020-2023  润新知