矩阵连乘DP模型
2014-03-19 10:49
323 查看
矩阵连乘
描述himdd有一天闲着无聊,随手拿了一本书,随手翻到一页,上面描述了一个神奇的问题,貌似是一个和矩阵有关的东西。
给出三个矩阵和其行列A1(10*100),A2(100*5),A3(5*50)。现在himdd要算出计算矩阵所要的乘法次数,他发现不同的计算次序,所要的乘法次数也不一样,
如:
(A1*A2)*A3 : 10*100*5+5*10*50=7500;
A1*(A2*A3) : 5*100*50+10*100*50 =75000;
他想知道计算矩阵所要的最少乘法次数是多少,很快一个解法就诞生了,有点小happy~~现在他想问问你是否也能找出一个解法呢?
注意:矩阵不可改变顺序。
输入有多组测试数据(<=100),每组表述如下:
第一行,有一个整数n矩阵的个数(1<=n<=100)
接下来有n行
第i行有两整数,r,c表示第i个矩阵的行列;(1<=r,c<=100)
输出输出计算矩阵所要的最少乘法次数。
样例输入
3 10 100 100 5 5 50
样例输出
7500
const int Max_N = 108 ; const int inf = 100000000 ; int x[Max_N] ; int dp[Max_N][Max_N] ; int n ; int DP(){ int i , j , k , len ; for(i = 1 ; i <= n ; i++) dp[i][i] = 0 ; for(i = 1 ; i + 1 <= n ; i++) dp[i][i+1] = x[i-1] * x[i] * x[i+1] ; for(len = 2 ; len <= n ; len++){ for(i = 1 ; i + len <= n ; i++){ j = i + len ; dp[i][j] = inf ; for(k = i ; k+1 <= j ; k++) dp[i][j] = min(dp[i][j] , dp[i][k] + dp[k+1][j] + x[i-1] * x[k] * x[j]) ; } } return dp[1] ; }
石子合并(一)
描述 有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。输入有多组测试数据,输入到文件结束。
每组测试数据第一行有一个整数n,表示有n堆石子。
接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开
输出输出总代价的最小值,占单独的一行
样例输入
3 1 2 3 7 13 7 8 16 21 4 18
样例输出
9 239
const int Max_N = 208 ; const int inf = 1000000008 ; char str[Max_N] ; int dp[Max_N][Max_N] ; int sum[Max_N] ; int x[Max_N] ; int n ; int DP(){ int i , j , len , k ; sum[0] = 0 ; for(i = 1 ; i <= n ; i++){ dp[i][i] = 0 ; sum[i] = sum[i-1] + x[i] ; } for(i = 1 ; i + 1 <= n ; i++) dp[i][i+1] = x[i] + x[i+1] ; for(len = 2 ; len <= n ; len++){ for(i = 1 ; i + len <= n ; i++){ j = i + len ; dp[i][j] = inf ; for(k = i ; k + 1 <= j ; k++) dp[i][j] = min(dp[i][j] , sum[j] - sum[i-1] + dp[i][k] + dp[k+1][j]) ; } } return dp[1] ; }
Splits the string
描述Hrdv is interested in a string,especially the palindrome string.So he wants some palindrome string.
A sequence of characters is a palindrome if it is the same written forwards and backwards. For example, 'abeba' is a palindrome, but 'abcd' is not.
A partition of a sequence of characters is a list of one or more disjoint non-empty groups of consecutive characters whose concatenation yields the initial sequence. For example, ('race', 'car') is a partition of 'racecar' into two groups.
Given a sequence of characters, we can always create a partition of these characters such that each group in the partition is a palindrome! Given this observation it is natural to ask: what is the minimum number of groups needed for a given string such
that every group is a palindrome?
For example:
'racecar' is already a palindrome, therefore it can be partitioned into one group.
'fastcar' does not contain any non-trivial palindromes, so it must be partitioned as ('f', 'a', 's', 't', 'c', 'a', 'r').
'aaadbccb' can be partitioned as ('aaa', 'd', 'bccb').
Input begins with the number n of test cases. Each test case consists of a single line of between 1 and 1000 lowercase letters, with no whitespace within.
输入Each test case consists of a single line of between 1 and 1000 lowercase letters, with no whitespace within.
输出For each test case, output a line containing the minimum number of groups required to partition the input into groups of palindromes.
样例输入
racecar fastcar aaadbccb
样例输出
1 7 3
const int Max_N = 1008 ; const int inf = 1008 ; char str[Max_N] ; int dp[Max_N][Max_N] ; int DP(){ int i , j , k , len , L = strlen(str) ; for(i = 0 ; i < L ; i++) dp[i][i] = 1 ; for(i = 0 ; i+1 < L ; i++) dp[i][i+1] = (str[i]==str[i+1] ? 1 : 2) ; for(len = 2 ; len < L ; len++){ for(i = 0 ; i + len < L ; i++){ j = i + len ; dp[i][j] = inf ; if(str[i] == str[j]){ if(dp[i+1][j-1] == 1) dp[i][j] = 1 ; else dp[i][j] = dp[i+1][j-1] + 2 ; } for(k = i ; k + 1 <= j ; k++) dp[i][j] = min(dp[i][j] , dp[i][k]+dp[k+1][j]) ; } } return dp[0][L-1] ; }
括号匹配(二)
描述给你一个字符串,里面只包含"(",")","[","]"四种符号,请问你需要至少添加多少个括号才能使这些括号匹配起来。如:
[]是匹配的
([])[]是匹配的
((]是不匹配的
([)]是不匹配的
输入第一行输入一个正整数N,表示测试数据组数(N<=10)
每组测试数据都只有一行,是一个字符串S,S中只包含以上所说的四种字符,S的长度不超过100
输出对于每组测试数据都输出一个正整数,表示最少需要添加的括号的数量。每组测试输出占一行
样例输入
4 [] ([])[] ((] ([)]
样例输出
0 0 3 2
const int Max_N = 108 ; const int inf = 1000000 ; int dp[Max_N][Max_N] ; char str[Max_N] ; int DP(){ int i , j , k , len , L = strlen(str) ; for(i = 0 ; i < L ; i++) dp[i][i] = 1 ; for(i = 0 ; i + 1 < L ; i++){ if(str[i] == '(' && str[i+1] == ')' || str[i] == '[' && str[i+1] == ']') dp[i][i+1] = 0 ; else dp[i][i+1] = 2 ; } for(len = 2 ; len < L ; len++){ for(i = 0 ; i + len < L ; i++){ j = i + len ; dp[i][j] =inf ; if(str[i] == '(' && str[j] == ')' || str[i] == '[' && str[j] == ']') dp[i][j] = min(dp[i][j] , dp[i+1][j-1]) ; for(k = i ; k + 1 <= j ; k++) dp[i][j] = min(dp[i][j] , dp[i][k] + dp[k+1][j]) ; } } return dp[0][L-1] ; }
删数游戏:
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, scoring10*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.
dp[i][j] 表示开区间(i , j)取完的最小加权和。
const int Max_N = 108 ; const int inf = 100000000 ; int x[Max_N] ; int dp[Max_N][Max_N] ; int n ; int DP(){ int i , j , k , len ; for(i = 1 ; i + 2 <= n ; i++) dp[i][i+2] = x[i] * x[i+1] * x[i+2] ; for(len = 3 ; len <= n ; len++){ for(i = 1 ; i + len <= n ; i++){ j = i + len ; dp[i][j] = inf ; for(k = i+1 ; k + 1 <= j ; k++) dp[i][j] = min(dp[i][j] , dp[i][k] + dp[k][j] + x[i]*x[k]*x[j]) ; } } return dp[1] ; }
回文字符串
描述所谓回文字符串,就是一个字符串,从左到右读和从右到左读是完全一样的,比如"aba"。当然,我们给你的问题不会再简单到判断一个字符串是不是回文字符串。现在要求你,给你一个字符串,可在任意位置添加字符,最少再添加几个字符,可以使这个字符串成为回文字符串。输入第一行给出整数N(0<N<100)
接下来的N行,每行一个字符串,每个字符串长度不超过1000.
输出每行输出所需添加的最少字符数
样例输入
1 Ab3bd
样例输出
2
const int Max_N = 1008 ; int dp[Max_N][Max_N] ; char str[Max_N] ; int DP(){ int i, j , k , len , L = strlen(str) ; for(i = 0 ; i < L ; i++) dp[i][i] = 0 ; for(i = 0 ; i+1 < L ; i++) dp[i][i+1] = (str[i] == str[i+1] ? 0 : 1) ; for(len = 2 ; len < L ; len++){ for(i = 0 ; i + len < L ; i++){ j = i + len ; dp[i][j] = j - i + 1 ; if(str[i] == str[j]) dp[i][j] = min(dp[i][j] , dp[i+1][j-1]) ; dp[i][j] = min(dp[i+1][j] + 1 , dp[i][j]) ; dp[i][j] = min(dp[i][j-1] + 1 , dp[i][j]) ; } } return dp[0][L-1] ; }
相关文章推荐
- 基于DP的矩阵连乘问题
- DP---矩阵连乘
- 矩阵连乘问题 DP
- DP--矩阵连乘
- [动态规划DP] 矩阵连乘
- 蓝桥杯 算法提高 矩阵乘法 (区间DP: 最优矩阵连乘)
- 51nod1021 石子归并 (dp 类似矩阵连乘)
- dp经典矩阵连乘-记忆化搜索实现
- 基于DP的矩阵连乘问题
- 区间DP-矩阵连乘问题
- VIJOS-P1312 能量项链 【区间DP--矩阵连乘】
- poj 1179 循环dp 类似矩阵连乘
- 区间DP-由矩阵连乘所想到的
- 矩阵连乘,使用备忘录,不知道算不算DP的一种?
- 矩阵连乘的最少次数——dp
- poj 1651 区间dp+矩阵连乘DP
- 多校第6场 HDU 3893&&JLU Drawing Pictures(数位DP变形,矩阵连乘)
- 区间DP之矩阵连乘
- 51nod 1021 石子归并(dp-矩阵连乘)
- soj 11600 Pick It 矩阵连乘模型 动态规划 acdream 1208 qj的奇怪宝具 noip 2006 energy 能量项链