求最少需要多少个硬币
无限硬币问题,每个硬币无限个
#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;
}
posted on
浙公网安备 33010602011771号