求最少需要多少个硬币
无限硬币问题,每个硬币无限个
#include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<stack> #include<cstdio> #include<queue> #include<map> #include<vector> #include<set> using namespace std; const int maxn=1010; const int INF=0x3fffffff; typedef long long LL; LL a[210]; int n,m; //无限硬币问题 int b[100001]; int main(){ cin>>n>>m; for(int i=0;i<n;i++) cin>>a[i]; for(int i=1;i<=m;i++) b[i]=INF; b[0]=0; for(int i=0;i<n;i++){ for(int j=a[i];j<=m;j++){ b[j]=min(b[j],b[j-a[i]]+1); } } for(int i=1;i<=m;i++) cout<<b[i]<<endl; return 0; }
如果需要打印组合
#include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<stack> #include<cstdio> #include<queue> #include<map> #include<vector> #include<set> using namespace std; const int maxn=1010; const int INF=0x3fffffff; typedef long long LL; LL a[210]; int n,m; //无限硬币问题 //打印组合 int minpath[maxn]; int b[100001]; int main(){ cin>>n>>m; for(int i=0;i<n;i++) cin>>a[i]; for(int i=1;i<=m;i++) b[i]=INF; b[0]=0; for(int i=0;i<n;i++){ for(int j=a[i];j<=m;j++){ if(b[j]>b[j-a[i]]+1){ minpath[j]=a[i]; b[j]=b[j-a[i]]+1; } } } int s; cin>>s; while(s){ cout<<minpath[s]<<" "; s-=minpath[s]; } return 0; }
有限硬币问题,每个硬币有数量限制
#include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<stack> #include<cstdio> #include<queue> #include<map> #include<vector> #include<set> using namespace std; const int maxn=1010; const int INF=0x3fffffff; typedef long long LL; //有限硬币问题 int num[110]; int val[110]; int b[10001]; int n,m; int main(){ cin>>n>>m; for(int i=0;i<n;i++) cin>>val[i]; for(int i=0;i<n;i++) cin>>num[i]; for(int i=1;i<=m;i++) b[i]=INF; b[0]=0; for(int i=0;i<n;i++){ for(int j=1;j<=num[i];j++){ for(int z=m;z>=val[i];z--){ //逆序 b[z]=min(b[z],b[z-val[i]]+1); } } } for(int i=1;i<=m;i++) { if(b[i]==INF) cout<<"-1"<<endl; else cout<<b[i]<<endl; } return 0; }
硬币组合数量
给定硬币面值,需要的钱,有多少种组合方案
没有数量限制
const int maxn=1010; const int INF=0x3fffffff; typedef long long LL; int a[10]={1,2,5,10,25}; //无限硬币问题 int dp[maxn]={0}; void js(){ dp[0]=1; //初值为1 for(int i=0;i<5;i++){ for(int j=a[i];j<251;j++) dp[j]+=dp[j-a[i]]; } } int main(){ int s; js(); while(cin>>s){ cout<<dp[s]<<endl; } return 0; }
如果有数量限制
定义dp[i][j],意思是用j个硬币实现金额i的方案数量
#include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<stack> #include<cstdio> #include<queue> #include<map> #include<vector> #include<set> using namespace std; const int maxn=1010; const int INF=0x3fffffff; //所有硬币组合,而且对硬币的数量有限制 int a[5]={1,5,10,25,50}; int dp[251][110]; int n; //先打表 void sovle(){ dp[0][0]=1; for(int i=0;i<5;i++){ for(int j=1;j<101;j++){ for(int k=a[i];k<251;k++) dp[k][j]+=dp[k-a[i]][j-1]; } } } int ans[251]={0}; int main(){ sovle(); for(int i=0;i<251;i++){ for(int j=0;j<101;j++) ans[i]+=dp[i][j]; //从0开始,因为dp[0][0]=1 } while(cin>>n){ cout<<ans[n]<<endl; } return 0; }