笔试真题

1.华为笔试第3题

题目描述:假如有1米和2米的线段若干,现需要拼接成4米的线段,一共有1+1+1+1,1+1+2,2+2, 3种拼接方法。
现在需要拼接m米线段,有C1,C2,C3,…线段可供选择,一共有多少种拼接方法。

输入:4 1 2
输入描述:第一个值为需要拼接的线段长度,后面的值为可供选择的线段长度

输出:3

解题思路:看到该题,和上一题有点类似,有点类似于硬币找零的问题,求一共有多少种找零的方法。
首先能想到的就是采用回溯法,列举出所有的可能,但是如果m很大的话时间复杂度太高了。
我们可以采用动态规划的思路去求解:
(1)状态定义:定义一个二维动态数组dp[i][j],表示前i种可供选择的线段拼接成长度j的线段最多有多少种拼接方法。
(2)状态转移方程:dp[i][j] = dp[i-1][j]+dp[i][j-c[i-1]]
(3)初始化:dp[0][i] = 0; dp[i][0] = 1
(4)返回值:dp[c.length][m]

代码

	public static void main(String[] args) {
     
		Scanner sc = new Scanner(System.in);
		String[] s = sc.nextLine().split(" ");
		int m = Integer.valueOf(s[0]);
		int[] c = new int[s.length-1];
		for (int i = 1; i < s.length; i++) {
     
			c[i-1] = Integer.valueOf(s[i]);
		}
		int[][] dp = new int[c.length+1][m+1];
		for (int i = 0; i < c.length+1; i++) {
     
			dp[i][0] = 1;
		}
		for (int i = 0; i < m+1; i++) {
     
			dp[0][i] = 0;
		}
		for (int i = 1; i < c.length+1; i++) {
     
			for (int j = 1; j < m+1; j++) {
     
				if(j >= c[i-1]) {
     
					dp[i][j] = dp[i-1][j]+dp[i][j-c[i-1]];
				}
				else {
     
					dp[i][j] = dp[i-1][j];
				}
			}
		}
		for (int i = 0; i < dp.length; i++) {
     
			System.out.println(Arrays.toString(dp[i]));
		}
		System.out.println(dp[c.length][m]);
	}

最终结果只通过了80%。。。

你可能感兴趣的:(算法刷题)