硬币问题

求最少需要多少个硬币

无限硬币问题,每个硬币无限个

#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;
}

  

原文地址:https://www.cnblogs.com/shirlybaby/p/12465275.html