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~~现在他想问问你是否也能找出一个解法呢?
注意:矩阵不可改变顺序。
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] ; }
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][n] ; }
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] ; }
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
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][n] ; }
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] ; }