您的位置:首页 > 其它

矩阵连乘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, 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.

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] ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: