现有n1+n2种面值的硬币,其中前n1种为普通币,可以任意取放,后n2种为纪念币,每种最多只能取一枚,每种硬币有一个面值,问能用多少种方法拼出m的面值?
1、递归做法
int visited[50]={0};
vector<vector<int>>vec1;
int func2(int coins[],int n1,int m,int sum){
if(sum==m){
cout<<sum<<endl;
vector<int>vec;
for(int i=0;i<n1;i++){
vec.push_back(visited[i]);
}
for(auto i : vec1){
if(i==vec){
return 0;
}
}
vec1.push_back(vec);
for(int i=0;i<n1;i++){
if(visited[i]==1){
cout<<coins[i]<<" ";
}
}
cout<<endl;
return 1;
}
int ans=0;
for(int i=0;i<n1;i++){
if(visited[i]==0 && sum+coins[i]<=m){
visited[i]=1;
ans+=func2(coins,n1,m,sum+coins[i]);
visited[i]=0;
}
}
return ans;
}
int func1(int coins[],int n1,int n2,int m){
int sum=0;
for(int i=n1;i<n1+n2;i++){
int tmp=coins[i];
sum+=func2(coins,n1,m,tmp);
}
sum+=func2(coins,n1,m,0);
return sum;
}
int main(){
int n1,n2,m;
cin>>n1>>n2>>m;
int coins[n1+n2];
for(int i=0;i<n1+n2;i++){
cin>>coins[i];
}
cout<<func1(coins,n1,n2,m)<<endl;
return 0;
}
2、动态规划做法(本做法只得到一个二维动态规划数组,之后的做法既简单不写了)
int main(){
int n1,n2,m;
cin>>n1>>n2>>m;
int coins[n1+n2];
for(int i=0;i<n1+n2;i++){
cin>>coins[i];
}
int matrix[n1][m+1];
// 0~i上货币随便用,怎么拼出j块钱
for(int i=0;i<n1;i++){
for(int j=0;j<m+1;j++) matrix[i][j]=-1;
}
//第0排
int tmp=coins[0];
for(int i=0;i<m+1;i++) matrix[0][i]=0;
while(m>tmp){
matrix[0][tmp]=1;
tmp+=coins[0];
}
//第0列
for(int i=0;i<n1;i++){
matrix[i][0]=0;
}
for(int i=1;i<n1;i++){
for(int j=1;j<m+1;j++){
int index=j;
int sum=0;
while(index>=0){
sum+=matrix[i-1][index];
index-=coins[i];
}
matrix[i][j]=sum;
}
}
for(int i=0;i<n1;i++){
for(int j=0;j<m+1;j++) cout<<matrix[i][j]<<" ";
cout<<endl;
}
return 0;
}