Problem Description
在一个国家仅有1分,2分,3分硬币,将钱N兑换成硬币有很多种兑法。请你编程序计算出共有多少种兑法。
Input
每行只有一个正整数N,N小于32768。
Output
对应每个输入,输出兑换方法数。
Sample Input
2934
12553
Sample Output
718831
13137761
母函数暂时不会,只能用背包做,dp[i][j]表示使用前i种钱换成j的总共方式。首先要考虑初始问题,dp[i][0]=1;有再多的钱换成0元只有一种方式。dp[1][a[1]* q]=1; 这个表示第一种钱的倍数有一种方式,比如表示第一种钱是3块的时候,dp[1][3]表示一张三块,dp[1][3*2]表示6块钱刚好可以用两张三块钱表示。
正常情况下的核心状态转移方程为
- if(i>j) {dp[i][j]=dp[i-1][j];}无法使用第i种钱,就是使用i-1种钱抓取j的方式数
- else {dp[i][j]=dp[i-1][j] dp[i][j-a[i]];}可以使用第i张,总个数就是不适用第i种的加上使用第i种的,不使用第i种就是dp[i-1][j],使用了i种就是dp[i][j-a[i]];其实这里有一个递归/调用自己的过程,使用了一张后dp[i][j-a[i]]在重新判断这个数能否使用i,如果能使用,再次拆分,一直拆到最后无法使用i为止。附上代码:
import java.util.Scanner;
/*
* 找零钱问题背包问题
*/
public class 杭电1284 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int dp[][]=new int[4][32768];
for(int i=1;i<4;i ) {dp[i][0]=1;}
for(int j=1;j<32768;j ) {dp[1][j]=1;}//这里a[i]刚好为i所以a[1]=1;可以简化不用数组
for(int i=1;i<4;i )
{
for(int j=1;j<32768;j )
{
if(i>j) {dp[i][j]=dp[i-1][j];}
else
dp[i][j]=dp[i-1][j] dp[i][j-i];//a[i]=i;就一分,两分,三分。
}
}
while(sc.hasNext())
{
int n=sc.nextInt();
System.out.println(dp[3][n]);
}
}
}
希望后面学了母函数能够在用母函数写出来!
更新母函数代码,直接套模板即可
import java.util.Scanner;
public class hdu1284 {
static long c1[];
static long c2[];
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
c1=new long[32769];
c2=new long[32769];
sovle(32768);
while(sc.hasNext())
{
int t=sc.nextInt();
System.out.println(c1[t]);
}
}
private static void sovle(int n) {
// TODO 自动生成的方法存根
for(int i=0;i<=n;i )
{
c1[i]=1;
c2[i]=0;
}
for(int i=2;i<=3;i )
{
for(int j=0;j<=n;j )
{
for(int k=0;k j<=n;k =i)
{
c2[k j] =c1[j];
}
}
for(int j=0;j<=n;j )
{
c1[j]=c2[j];c2[j]=0;
}
}
}
}
原创公众号:「bigsai」,回复【bigsai】获取珍藏pdf书籍资源,回复【进群】即可加入leetcode打卡群。主要分享Java,数据结构与算法,期待你的关注!