1. 程式人生 > >演算法_動態規劃_乘法表問題

演算法_動態規劃_乘法表問題

問題描述:
定義於字母表∑{a,b,c)上的乘法表如表所示
表1∑乘法表
a b c
a b b a
b c b a
c a c c
依此乘法表,對任一定義於∑上的字串,適當加括號表示式後得到一個表示式。例如,對於字串x=bbbba,它的一個加括號表示式為i(b(bb))(ba)。依乘法表,該表示式的值為a。試設計一個動態規劃演算法,對任一定義於∑上的字串x=x1x2…xn,計算有多少種不同的加括號方式,使由x匯出的加括號表示式的值為a
要求:
輸入:輸入一個以a,b,c組成的任意一個字串。
輸出:計算出的加括號方式數。
思路:
建立一個三位陣列,用於記錄一段連續的序列內通過加括號可得到a、b、c的方式數,然後往長度方向擴充套件,因為每兩個字母相乘的結果已給出,所以可通過加和乘運算求出更大長度的字串得到a、b、c的方式數

問題分析:
陣列維數為:p[n][n][3];
p[i][j][k] 表示 字串xix(i+1)….xj的表示式的值為k(k>=0 k <=2,k=0表示a…) 的方式數;
遞推式為:
p[i][j][0]= sum(p[i][t][0]*p[t+1][j][2]+ p[i][t][1]*p[t+1][j][2]+p[i][t][2]*p[t+1][j][0])
p[i][j][1]與p[i][j][2]類似p[i][j][0] 的求法 t>=i 並且t

import java.util.Scanner;

public class Main {
    private
static int n; private static String s; private static int[][][] dp; /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Scanner sc=new Scanner(System.in); s=sc.next(); n=s.length(); dp=new int
[n+1][n+1][3]; for(int i=1;i<=n;i++){ dp[i][i][s.charAt(i-1)-'a']=1; } for(int r=1;r<=n;r++){ for(int i=1;i<=n;i++){ int j=i+r; if(j>n){ continue; } for(int k=1;k<j;k++){ dp[i][j][0]+=dp[i][k][0]*dp[k+1][j][2]+dp[i][k][1]*dp[k+1][j][2]+dp[i][k][2]*dp[k+1][j][0]; dp[i][j][1]+=dp[i][k][0]*dp[k+1][j][0]+dp[i][k][0]*dp[k+1][j][1]+dp[i][k][1]*dp[k+1][j][1]; dp[i][j][2]+=dp[i][k][1]*dp[k+1][j][0]+dp[i][k][2]*dp[k+1][j][1]+dp[i][k][2]*dp[k+1][j][2]; } } } System.out.println(dp[1][n][0]); } }