动态规划解乘法表问题

简述:

这道题是标准的动态规划题

定义于字母表∑{a,b,c)上的乘法表如表1所示
表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组成的任意一个字符串。
输出:计算出的加括号方式数。


算法描述:

从最小的两个字符的括号开始加起,逐步增加括号内字符的数量,从下至上的动态规划

其实就是从小到大给字符串加括号,大括号的结果依赖于小括号的结果

例如(abc)中(abc)依赖于(ab) * (c)  以及 (a)*(bc)

所以由此看来,大括号的结果就是小括号结果的继续, 其实归到地就是单个字符间的结果,

这也就是循环刚开始的时候,是从连续的两个字符的括号开始的,并逐步向上规约


package dynamic_programming;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class MultiplicationTable {
	private static String str = null;
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
		BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
		try{
			out: while(true){
				System.out.print("Please input a string: ");
				if((str = bufferedReader.readLine()).length() == 0){
					System.out.println("Empty Input! ");
					continue;
				}
				for(char ch : str.toCharArray()){
					if(ch > 'c' || ch < 'a'){
						System.out.println("Illegal Input! input among 'a', 'b' or 'c'");
						continue out;
					}
				}
				break;
			}
		}catch(IOException e){
			e.printStackTrace();
		}
		int n = str.length();
		int a[][][] = new int[n][n][3];
		
		//intialize the array
		for(int i = 0; i < n; i++)
			for(int j = 0; j < n; j++)
				for(int k = 0; k < 3; k++)
					a[i][j][k] = 0;
		
		//get info from the given string 
		for(int i = 0; i < n; i++)
			a[i][i][str.charAt(i) - 'a'] = 1;//here 0:a, 1:b, 2:c
		
	    for(int k = 1; k < n; k++) { //the length of a pair of brackets from 1 to n - 1
	        for(int i = 0; i < n - k; i++) {   //the position of the first bracket
	            int j = i + k;   
	            for(int t = i;t < j;t++) { //t is the position of the second bracket from i to j - 1 
	                a[i][j][0] += a[i][t][2] * a[t+1][j][0]   //c * a = a
	                            + a[i][t][0] * a[t+1][j][2]   //a * c = a
	                            + a[i][t][1] * a[t+1][j][2];  //b * c = a
	                
	                a[i][j][1] += a[i][t][0] * a[t+1][j][0]   //a * a = b
	                            + a[i][t][0] * a[t+1][j][1]   //a * b = b
	                            + a[i][t][1] * a[t+1][j][1];  //b * b = b
	                
	                a[i][j][2] += a[i][t][1] * a[t+1][j][0]   //b * a = c
	                           + a[i][t][2] * a[t+1][j][1]    //c * b = c
	                           + a[i][t][2] * a[t+1][j][2];   //c * c = c
	            }   
	        }   
	    }
	    // a[0][n-1][0] means the number of methods str[0 to n-1] which equals a
	    System.out.println("Methods Of Adding Brackets: " + a[0][n-1][0]);  
	}
}


输出:









评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值