动态规划:HDU1248-钱币兑换问题

解题心得:

(青蛙跳台阶:有n阶台阶,青蛙可以一次跳一阶也可以一次跳两阶,问总共有多好中跳法)

1、之前把这个问题的思路弄错了,以为是递推,就像青蛙跳台阶,用斐波那契求解。但是用斐波那契肯定会超范围。反过来想自己的思路其实是错的。青蛙跳台阶其实要区分顺序,比如三级台阶,先跳两级再跳一级和先跳两级再跳一级是两种不同的方法,但是钱币问题两分和一分都可以凑成三分钱但是不分先后顺序。

2、凑硬币有三种算法,先说第一种。第一种就是完全背包问题,动态规划,一元的只有一种凑法,全是一元的,然后规划二元的,将两个一元的可以用一个一元的代换,所以可以代换一个一元的就多一种凑法,因为可以选择替换或者不替换,再逐步扩大钱数就可以了,三元的同上。

3、第二种算法,和第一种比较相似,只不过先是凑的三元的,所以先看可以凑多少个三元的,n/3种不够的直接用一来填补就行了,n/3+1,+1部分就是全用一元的来组成的情况。然后就是逐步减去i个三元用二元来代替,思想方法同第二种,加起来就行了



题目

钱币兑换问题

http://acm.hdu.edu.cn/showproblem.php?pid=1284

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3261 Accepted Submission(s): 1842


Problem Description
在一个国家仅有1分,2分,3分硬币,将钱N兑换成硬币有很多种兑法。请你编程序计算出共有多少种兑法。

Input
每行只有一个正整数N,N小于32768。

Output
对应每个输入,输出兑换方法数。

Sample Input
2934
12553

Sample Output
718831
13137761

Author
SmallBeer(CML)

Source
杭电ACM集训队训练赛(VII)




方法一:
#include
#include
long long num[32770];
int main()
{
    memset(num,0,sizeof(num));
    num[0] = 1;
    for(int i=1;i<=3;i++)
        for(int j=i;j<=32768;j++)
            num[j] += num[j-i];
    int n;
    while(~scanf("%d",&n))
    {
        printf("%lld\n",num[n]);
    }
}
方法二:
#include
using namespace std;
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        long long sum = 0;
        sum = n/3 + 1;
        for(int i=0;i<=n/3;i++)
        {
            int t = (n-i*3)/2;
            sum += t;
        }
        printf("%lld\n",sum);
    }
}
方法三:(母函数)
#include
using namespace std;
int main()
{
    int c1[32770],c2[32770];
    int n;
    for(int i=0;i<=32768;i++)
    {
        c1[i] = 1;
        c2[i] = 0;
    }
    for(int i=2;i<=3;i++)
    {
        for(int j=0;j<=32768;j++)
        {
            for(int k=0;k+j<=32768;k+=i)
            {
                c2[k+j] +=  c1[j];
            }
        }
        for(int k=0;k<=32768;k++)
        {
            c1[k] = c2[k];
            c2[k] = 0;
        }
    }
    while(~scanf("%d",&n))
    {
        printf("%d\n",c1[n]);
    }
}













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