UVa 674 - coin change

之前做过一道HDOJ上很类似的一道题,当时用的是枚举(依次从大到小枚举某一面值使用的次数,然后把所有情况相加),今天在UVa动态规划里看到这道题,一下子就没思路了,后来翻到了Rookie_Yang的代码,实在不理解。。硬着头皮求助队友,最后找到了正确的状态转移方程,才理解他的代码是优化过的;

dp(i, j)表示 i 分钱用前 j(0,1,2,3,4) 种类型的硬币兑换总的方法;

2012.4.2  以下注释中的考虑没必要,因为dp()中已经对j == 0的情况处理了。

/* 记忆画搜索时还需要注意:对于 s[0..4][0],要在搜索前初始化(因为最终追溯到的是 s[0..4][0] 这 5 个数)。 */

# include <stdio.h>

const int c[] = {1, 5, 10, 25, 50};

int s[7500][5];

int dp(int i, int j)
{
int k;
if (j == 0) return s[i][j] = 1;
if (s[i][j] > 0) return s[i][j];
for (k = 0; k <= i; k += c[j])
s[i][j] += dp(i-k, j-1);
return s[i][j];
}

int main()
{
int n, i;

//没必要,已经在dp()中考虑了: for (i = 0; i < 5; ++i) s[i][0] = 1;

while (~scanf("%d", &n))
printf("%d\n", dp(n, 4));

return 0;
}

posted on 2012-03-31 20:39  getgoing  阅读(620)  评论(2编辑  收藏  举报

导航