论坛首页 编程语言技术论坛

Ruby每周一测 - 找零钱

浏览 26608 次
精华帖 (4) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-03-27  
庄表伟 写道
Trustno1 写道
引用
我先假设如果有找零的方案的话,零钱的个数不大于50(50*20也有10刀了,应该是不小的零钱数量吧,呵呵),算法思想无非是穷举加上回退操作。简单描述如下:首先拿出一个最大的零钱给客户(当然,存在的话),然后再取一个最大的零钱(合理的),。。。以此类推。。当某一次取操作,发现不成功时,则叫客户把你上次给他的钱退回,然后换一个次大的零钱。。。以此类推。。。这样得到的方案肯定是最优的

哈哈LS诸位都是贪心鬼阿.但是很不幸的告诉各位,找零钱等价背包问题,如果要找全局最优解的话就不要往贪心上化功夫了.贪心找不到全局最优解,贪心法的最优子结构性质需要根据硬币面值和初次贪心选择来定,特定组合的面值或者特定选择顺序可以得到最优解一般情况下是局部最优解!还是用动态规划靠谱一点.通项也不是很难得了 C(t)=min{1+C(t-di),di<=t,1<=i<=n};C(t)是t元时的最小值,n是硬币种类,di是硬币面值.复杂度o(n^2).

直觉当然很重要,但是可以说大量的算法问题都是违犯直觉的赫赫.


我直觉上也认为,这题目不能通过“剪枝”来优化。不过,麻烦写一个code来看看吧,光看你的公式,不明白的。


这是ruby quzi阿,俺不懂ruby的说.
这公式也没啥难的巴,直接手动算几个case不就知道怎么做了么?

0 请登录后投票
   发表时间:2008-03-27  
那你可以写java代码嘛,我来翻译成ruby code好了。
0 请登录后投票
   发表时间:2008-03-28  
不知道怎样速度算快?
我用javascript写了一个。基本上计算没有超过100毫秒的(最后结果有上百个item时),不过如果amount很大而coins都很小,会stack overflow。。。
0 请登录后投票
   发表时间:2008-03-28  
to: T1 and hax

其实,我觉得这个问题,未必要局限于Ruby,各种语言都可以来试试呀。

欢迎贴代码上来 
0 请登录后投票
   发表时间:2008-03-28  
庄表伟 写道
to: T1 and hax

其实,我觉得这个问题,未必要局限于Ruby,各种语言都可以来试试呀。

欢迎贴代码上来 


偶的笔记本没电了,等我充好电就贴上来。
0 请登录后投票
   发表时间:2008-03-28  
庄表伟 写道
to: T1 and hax

其实,我觉得这个问题,未必要局限于Ruby,各种语言都可以来试试呀。

欢迎贴代码上来 

这个问题的解法在算法里面的难度,大致就相当于你写Java查API的级别,连脑子都要不要动的.当然不熟算法就没办法了,谁让你平时不接触数学呢?你可以看一下算法设计方面的书,随便哪一本,必有一章叫做“动态规划”,看过之后就清楚了.

如果真有那么多时间,想要在这题目上动脑子的话.不如给出这个题目贪心法的正确性证明,这还是要费些脑子的.
另外这题,即便在C下面,数据量上万的话都要20-30ms,还要做优化.所以Ruby下面就不要想在100ms级别解决了.凡是能在这个级别以下的基本上都不是最优解,赫赫.


0 请登录后投票
   发表时间:2008-03-28  
如果只是想知道的答案的话,
可以去这里
http://acm.nankai.edu.cn
注册个号,找1132题.
题目稍微有差异,但是思路相同.
0 请登录后投票
   发表时间:2008-03-28  
function makeChange1(amount, coins) {
	if (coins == null) coins = [25, 10, 5, 1];
	if (coins.cache == null) coins.cache = {};
	for (var i = 0; i < coins.length; i++) {
		var c = coins[i];
		var o = coins.cache[c] = {length:1};
		o[c] = 1;
	}
	return mapToArray(_makeChange1(amount, coins, Number.POSITIVE_INFINITY));
}

// convert Map<int, int> to List<int>
// {1:2,2:0,3:1} => [1,1,3]
function mapToArray(map) {
	var a = [];
	for (var k in map) {
		k = parseInt(k, 10);
		if (isNaN(k)) continue;
		var v = map[k];
		for (var i = 0; i < v; i++) a.push(k);
	}
	return a.sort(compare);
}

function compare(a, b) {
	return b - a;
}

function _makeChange1(amount, coins, max) {
	var x = coins.cache[amount];
	if (x) return x.length < max ? x : null;
	
	var best = null;
	
	for (var i = 0; i < coins.length; i++) {
		var c = coins[i];
		if (c * max < amount) break;
		var m = amount % c;
		if (m == 0) {
			n = amount / c;
			max = n - 1;
			best = {length:n}; best[c] = n;
		} else if (m == amount) {
			continue;
		} else {
			var x = _makeChange1(amount - c, coins, max - 1);
			if (x == null) continue;
			max = x.length - 1;
			best = x; best[c] = best[c] ? best[c] + 1 : 1;
		}
	}
	coins.cache[amount] = best;
	return best;
}

function eq(a, b) {
	if (a === b) return true;
	if (a instanceof Array && b instanceof Array && a.length == b.length) {
		for (var i = 0, n = a.length; i < n; i++) {
			if (a[i] != b[i]) return false;
		}
		return true;
	}
	return false;
}

function assertEq(a, b) {
	if (!eq(a, b)) throw Error(a + ' != ' + b);
}

var makeChange = makeChange1;

assertEq(makeChange(25), [25]);
assertEq(makeChange(10), [10]);
assertEq(makeChange(1), [1]);
assertEq(makeChange(5, [3, 2]), [3, 2]);
assertEq(makeChange(5, [4, 3, 2]), [3, 2]);
assertEq(makeChange(39), [25, 10, 1, 1, 1, 1]);
assertEq(makeChange(14, [10, 7, 1]), [7, 7]);
assertEq(makeChange(14, [5, 3, 2]), [5, 5, 2, 2]);
assertEq(makeChange(12, [22, 3, 2]), [3, 3, 3, 3]);
assertEq(makeChange(38, [20, 19, 1]), [19, 19]);

var t1 = new Date().getTime();
var test = makeChange(31415926, [100000,1000,10,1]);
var t2 = new Date().getTime();
WScript.Echo(test.length, '[' + test + ']', ' use time:', t2 - t1);


输出结果:
D:\sjhe\js\test\change>cscript change.js
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

427 [100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,10000
0,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,1
00000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,1000
00,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,
100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100
000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000
,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,10
0000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,10000
0,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,1
00000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,1000
00,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,
100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100
000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000
,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,10
0000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,10000
0,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,1
00000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,1000
00,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,
100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100
000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000
,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,10
0000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,10000
0,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,1
00000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,1000
00,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,
100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100
000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000,100000
,100000,100000,100000,100000,100000,100000,1000,1000,1000,1000,1000,1000,1000,10
00,1000,1000,1000,1000,1000,1000,1000,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10
,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,1
0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,1,1,1,
1,1,1]  use time: 16

用了16ms。

0 请登录后投票
   发表时间:2008-03-28  
我也来贴一个

依据coins[i] = 1 + min{coins[i - d[j]]}

c语言风格,不要笑

def make_change(amount, coins = [25, 10, 5, 1])
  
  c = Array.new
  choice = Array.new
  result = Array.new
  minchoice = 0
  
  c[0] = 0
  
  for i in 1..amount
    min = 100000
    for j in 0..(coins.size() - 1)
      if coins[j] <= i and c[i - coins[j]] < min
        min = c[i - coins[j]]
        minchoice = j
      end
      c[i] = 1 + min
      choice[i] = minchoice
    end
  end

  if c[amount] == 100001
    return nil
  else
    while amount > 0
      result.push(coins[choice[amount]])
      amount = amount - coins[choice[amount]]
    end
    result
  end
  
end

#print make_change(50)
#puts make_change(1)
#puts make_change(9,[10,2,1])
#puts make_change(8,[10,4,2])
#puts make_change(19,[10,4,2,1])
#puts make_change(38, [20, 19, 1])
#puts make_change(11, [10, 1]) 


ps:怎么测试跑的速度?
0 请登录后投票
   发表时间:2008-03-28  
我也写了一个,不知道对不对
def make_change(amount, coins = [25, 10, 5, 1])
  return nil if amount == 0
  return [amount] if coins.include? amount
  coins_count = []
  valid_coins = coins.select{|coin| coin < amount}
  valid_coins.each do |coin|
    counter = [amount]
    idx = 0
    while  counter[idx] >= coin do
      counter << counter[idx] - coin
      counter[idx] = coin
      idx = idx.next
    end
    if counter[idx] > 0
      counter << make_change(counter[idx], valid_coins)
    else
      counter.delete_at(idx)
    end
    coins_count << counter
  end
  
  min = 9999
  result = []
  coins_count.each do |counter|
    if counter.size < min
      min = counter.size
      result = counter
    end
  end
 
  return result
end

puts make_change(380,[20,19,1])
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics