在一个国家仅有1分,2分,3分硬币,将钱N兑换成硬币有很多种兑法。请你编程序计算出共有多少种兑法。
Input
每行只有一个正整数N,N小于32768。
Output
对应每个输入,输出兑换方法数。
Sample Input
2934 12553
Sample Output
718831 13137761
第一种思想:他是要求完全背包的分配方案数,和原先学习的完全背包不太一样。
思想就是每次更改一个硬币的面值(当然因此剩余的钱要相应减少),比如4的话:
可以有3种情况:
1,1,1,1
1,1 ,2
2 ,2
然后你会发现2的话是:
1,1
2
4可以看作是只换成1的方案数 加上 2能换成任意面值的方案数 的总和,因为剩余的两种方案只是在得到2以后加上一张2面值的硬币,所以有如下规律:f(n)=f ( n - v[i] )+f( n );即:n的方案数=n已有的方案数+添加一种新的面值的方案数,这里每次添加的新的面值就一个,所以f(n- v [i] )是等于f(填一个新的面值的硬币)的。
#include<iostream>
#include<cmath>
#define LL long long
using namespace std;
LL s[32769];
//完全背包,或者思维,还不太懂
void dp(){
s[0]=1;
for(int j=1;j<=3;j++)
for(int i=1;i<=32768;i++){
s[i]+=s[i-j];
}
}
int main(){
int n;
dp();
while(cin>>n){
cout<<s[n]<<endl;
}
return 0;
}
另一种方法是用直接想的解决,你先用n个3元的,看剩下能拿几张2元的,最后剩余的就全是1元的了。
然后就是3元的可以拿i个,2元的可以拿(n-3*i)/2+1个,i:0~i。一层循环,遍历即可。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
int N;
int main()
{
while(~scanf("%d", &N))
{
int s = 0;
for(int i = 0 ; i <= N/3 ; i++)
{
int t = (N-3*i)/2+1;//2也是要从0个~m个算起,对于每一次的i个3都是,所以每次都要加1。
s += t;
}
printf("%d\n", s);
}
return 0;
}