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

Multiplication Puzzle
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 11239   Accepted: 6980

Description

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.

Sample Input

6
10 1 50 50 20 5

Sample Output

3650

Source

Northeastern Europe 2001, Far-Eastern Subregion

题意:

有N张写有数字的卡片排成一行,按一定次序从中拿走N-2张(第1张和最后一张不能拿),每次只拿一张,取走一张卡片的同时,会得到一个分数,分值的计算方法是:要拿的卡片,和它左右两边的卡片,这三张卡片上数字的乘积。按不同的顺序取走N-2张卡片,得到的总分可能不相同,求出给定一组卡片按上述规则拿取的最小得分。

题解:

最优矩阵链乘问题。刘汝佳紫书P277。

1.在取牌的过程中,必定存在一张最后取的牌,可知这张牌左右两边的牌都已经取完了(除了两端点)。于是“最后取的牌”,就把区间分成了两段。由于这两段区间的取牌(即得分情况)互不影响,故可以分开求值。那又怎样才能知道最后取哪张牌才能使得取值最优呢?枚举区间内每一张牌作为最后取的牌,取最优值。

2.对于被分开的左右两段区间,又可各自根据步骤1得到最优值。

3.紫书中区间的写法是左闭右开,但个人觉得不好理解,于是就写成自己所熟悉的闭区间。

记忆化搜索:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <sstream>
#include <algorithm>
using namespace std;
#define pb push_back
#define mp make_pair
#define ms(a, b) memset((a), (b), sizeof(a))
#define eps 0.0000001
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int maxn = +; LL p[maxn], dp[maxn][maxn]; LL dfs(int l, int r) //区间[l, r]中每个元素都可以取走
{
if(l>r) return ;
if(dp[l][r]!=LNF) return dp[l][r]; for(int k = l; k<=r; k++)
dp[l][r] = min(dp[l][r], dfs(l,k-) + dfs(k+,r) + p[l-]*p[k]*p[r+]); return dp[l][r];
} int main()
{
int n;
scanf("%d",&n);
for(int i = ; i<=n; i++)
scanf("%lld",&p[i]); for(int i = ; i<n; i++)
for(int j = ; j<=n; j++)
dp[i][j] = LNF; cout<<dfs(, n-)<<endl;
return ;
}

递推:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <sstream>
#include <algorithm>
using namespace std;
#define pb push_back
#define mp make_pair
#define ms(a, b) memset((a), (b), sizeof(a))
#define eps 0.0000001
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int maxn = +; LL p[maxn], dp[maxn][maxn]; int main()
{
int n;
scanf("%d",&n);
for(int i = ; i<=n; i++)
scanf("%lld",&p[i]); memset(dp, , sizeof(dp));
for(int l = ; l<=n-; l++)
for(int r = l; r<=n-; r++)
dp[l][r] = LNF; for(int len = ; len<=n-; len++)
{
for(int l = ; l<=n--len+; l++) //能取的区间为[2, n-1]
{
int r = l + len - ;
for(int k = l; k<=r; k++)
dp[l][r] = min(dp[l][r], dp[l][k-] + dp[k+][r] + p[l-]*p[k]*p[r+]);
}
} cout<< dp[][n-] <<endl; }

POJ1651 Multiplication Puzzle —— DP 最优矩阵链乘 区间DP的更多相关文章

  1. UVa 10003 切木棍(区间DP+最优矩阵链乘)

    https://vjudge.net/problem/UVA-10003 题意: 有一根长度为L的棍子,还有n个切割点的位置.你的任务是在这些切割点的位置处把棍子切成n+1部分,使得总切割费用最小.每 ...

  2. ZOJ 1276 "Optimal Array Multiplication Sequence"(最优矩阵链乘问题+区间DP)

    传送门 •题意 矩阵 A(n×m) 和矩阵 B(m×k) 相乘,共做 n×m×k 次乘法运算: 给你 n 个矩阵,求这 n 个矩阵的最优结合方式,使得做的总乘法运算次数最少: •题解 定义dp(i,j ...

  3. POJ 1651 Multiplication Puzzle(类似矩阵连乘 区间dp)

    传送门:http://poj.org/problem?id=1651 Multiplication Puzzle Time Limit: 1000MS   Memory Limit: 65536K T ...

  4. POJ1651:Multiplication Puzzle(区间DP)

    Description The multiplication puzzle is played with a row of cards, each containing a single positi ...

  5. POJ1651:Multiplication Puzzle(区间dp)

    Multiplication Puzzle Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9419 Accepted: 5850 ...

  6. poj1651 Multiplication Puzzle

    比较特别的区间dp.小的区间转移大的区间时,也要枚举断点.不过和普通的区间dp比,断点有特殊意义.表示断点是区间最后取走的点.而且一个区间表示两端都不取走时中间取走的最小花费. #include &l ...

  7. dp方法论——由矩阵相乘问题学习dp解题思路

    前篇戳:dp入门——由分杆问题认识动态规划 导语 刷过一些算法题,就会十分珍惜“方法论”这种东西.Leetcode上只有题目.讨论和答案,没有方法论.往往答案看起来十分切中要害,但是从看题目到得到思路 ...

  8. 蓝桥 ADV-232 算法提高 矩阵乘法 【区间DP】

      算法提高 矩阵乘法   时间限制:3.0s   内存限制:256.0MB      问题描述 有n个矩阵,大小分别为a0*a1, a1*a2, a2*a3, ..., a[n-1]*a[n],现要 ...

  9. tyvj 1198 矩阵连乘——区间dp

    tyvj 1198 矩阵连乘 题目描述 一个n*m矩阵由n行m列共n*m个数排列而成.两个矩阵A和B可以相乘当且仅当A的列数等于B的行数.一个N*M的矩阵乘以一个M*P的矩阵等于一个N*P的矩阵,运算 ...

随机推荐

  1. 洛谷 [P2148] E&G

    SG函数的应用 首先每一组都是独立的,所以我们可以求出每一组的SG值异或出来. 那么怎么求每一组的SG值呢,网上的题解都是打表找规律,但其实这个规律是可以证明的 先看规律: x为奇数,y为奇数:SG= ...

  2. POJ 3080 多个串最长公共子序列

    求多个串最长公共子序列,字典序最小输出.枚举剪枝+kmp.比较简单,我用find直接查找16ms #include<iostream> #include<string> #in ...

  3. luogu P3420 [POI2005]SKA-Piggy Banks

    题目描述 Byteazar the Dragon has NN piggy banks. Each piggy bank can either be opened with its correspon ...

  4. redis集群设置密码详解

    原文:http://lookingdream.blog.51cto.com/5177800/1827851 注意事项: 1.如果是使用redis-trib.rb工具构建集群,集群构建完成前不要配置密码 ...

  5. 管理weblogic服务的启动和停止

    2012-11-10 12:58 26036人阅读 评论(4) 收藏 举报 分类: WebLogic(10) 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 介绍 Weblog ...

  6. Mac Ubuntu ----端口被占用

    Mac下使用lsof(list open files)来查看端口占用情况,lsof 是一个列出当前系统打开文件的工具. 使用 lsof 会列举所有占用的端口列表: 1 $ lsof 使用less可以用 ...

  7. Jsp在Web.xml中的配置

    以下列出web.xml经常使用的标签元素及这些标签元素的功能: 1.指定欢迎页面.比如: <welcome-file-list> <welcome-file-list> < ...

  8. MVC5中Model层开发数据注解 EF Code First Migrations数据库迁移 C# 常用对象的的修饰符 C# 静态构造函数 MSSQL2005数据库自动备份问题(到同一个局域网上的另一台电脑上) MVC 的HTTP请求

    MVC5中Model层开发数据注解   ASP.NET MVC5中Model层开发,使用的数据注解有三个作用: 数据映射(把Model层的类用EntityFramework映射成对应的表) 数据验证( ...

  9. js 监控浏览器关闭(完美兼容chrome & ie & fire fox)

    var UnloadConfirm = {}; UnloadConfirm.MSG_UNLOAD = "数据尚未保存,离开后可能会导致数据丢失\n\n您确定要离开吗?"; Unlo ...

  10. sqlite学习笔记10:C语言中使用sqlite之查询和更新数据

    前面说到的 sqlite_exec() 中的第三个參数, SQLite 将为 sql 參数内运行的每一个 SELECT 语句中处理的每一个记录调用这个回调函数. 本节加入了两个函数.selectFro ...