火柴拼接数字的游戏

用 n 根火柴棍能组成多少个非负整数?火柴不必用完,如2根火柴可以组成 1 ,3 根火柴可以组成 1 7 ,4 根火柴可以组成  1, 4, 7, 11

数字                   0, 1, 2, 3, 4, 5, 6, 7, 8, 9 
需要的火柴数   6, 2, 5, 5, 4, 5, 6, 3, 7, 6
 
令 d[i] 为用 i 根火柴(全部用上)可以组成的数字个数,则在这些数字之后加上数字 0, 1, ..., 9 得到新数字,即 i 根火柴组成的数字数目 d[i] 可以 累计到 i + c[j] 根火柴组成的数字数目 d[i+c[j]] 之内 ( j = 0, ..., 9 c[j] 为组成数字 j 需要的火柴数目) 

第一个数字不能为 0 所有 i = 0 时 不能累加到 i + c[0], 用 小于等于 n 根火柴组成的总数目 f(n) = d(1) + d(2) + .. + d(n)

参考《算法竞赛入门经典训练指南》,刘汝佳,陈锋,P110

 

// 用 n 根火柴棍能组成多少个非负整数?火柴不必用完,如2根火柴可以组成 1 ,
// 3 根火柴可以组成 1 7 ,4 根火柴可以组成  1, 4, 7, 11
//
// 数字			0, 1, 2, 3, 4, 5, 6, 7, 8, 9	
// 需要的火柴数  	6, 2, 5, 5, 4, 5, 6, 3, 7, 6
// 
// 令 d[i] 为用 i 根火柴(全部用上)可以组成的数字个数,则在这些数字之后
// 加上数字 0, 1, ..., 9 得到新数字,即 i 根火柴组成的数字数目 d[i] 可以
// 累计到 i + c[j] 根火柴组成的数字数目 d[i+c[j]] 之内 ( j = 0, ..., 9 )
// c[j] 为组成数字 j 需要的火柴数目
//
// 第一个数字不能为 0 所有 i = 0 时 不能累加到 i + c[0]
//
// 用 小于等于 n 根火柴组成的总数目 f(n) = d(1) + d(2) + .. + d(n)
//
public class StickAndNumber {
	
	// 用小于等于 n 根火柴能组成的数字的数目
	public static int numbersFromStick(int n) {
		
		int[] d = new int[n+1];
		int[] c = { 6,2,5,5,4,5,6,3,7,6 };
		
		d[0] = 1;
		for ( int i=1; i<=n; i++ ) d[i] = 0;
				
		for ( int i=0; i<n; i++ ) {
			for ( int j=0; j<=9; j++) {
				if ( !(i==0&&j==0) && i+c[j]<=n )
					d[i+c[j]] += d[i];
			}
		}
		
		int sum = 0;
		for ( int i=1; i<=n; i++ ) {
			sum += d[i];
		}
		
		return (n<6)?sum:(sum+1);
		
	}

	// 测试
	public static void main(String[] args) {
		int[] v = { 2, 3, 4 };
		for ( int x : v ) {
			System.out.printf("%d:%d%n",x,numbersFromStick(x));
		}
	}

}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值