动态规划–找零钱问题
有n种硬币,第i种硬币的价值和重量分别为p[i]和w[i],现在需要用这n种硬币找出y元的零钱,求找零钱的方案使得总重量最小。注:p[1]=1。
方法一:
#include<stdio.h>
int main(){
int n,y,p[100],w[100],sec[100][100],f[100][100],i,j,k,x,min,a[100];
scanf("%d %d",&n,&y);
for(i=1;i<=n;i++)
scanf("%d",&p[i]);
for(i=1;i<=n;i++)
scanf("%d",&w[i]);
for(j=0;j<=y;j++){ //使用前一种硬币
f[1][j]=w[1]*j;
sec[1][j]=j; //记录硬币使用数量
}
for(i=2;i<=n;i++){ //使用前i种硬币凑成j的最小重量
for(j=0;j<=y;j++){
if(j==0){
f[i][j]=0;
sec[i][j]=0;
}
else{
x=j/p[i]; //向下取整
min=1e6;
for(k=0;k<=x;k++){
if(min>(f[i-1][j-k*p[i]])+k*w[i]){
min=f[i-1][j-k*p[i]]+k*w[i];
sec[i][j]=k;
}
}
f[i][j]=min;
}
}
}
for(i=n,j=y;i>=1;i--){
a[i]=sec[i][j];
j-=p[i]*sec[i][j];
}
for(i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\n%d",a[n],f[n][y]);
return 0;
}
方法二:
#include<stdio.h>
int main(){
int n,y,p[100],w[100],sec[100][100],f[100][100],i,j,a[100]={0};
scanf("%d %d",&n,&y);
for(i=1;i<=n;i++)
scanf("%d",&p[i]);
for(i=1;i<=n;i++)
scanf("%d",&w[i]);
for(j=1;j<=y;j++){ //初始化:使用前一种硬币
f[1][j]=w[1]*j;
sec[1][j]=1; //记录硬币种号(即题中的i数组)
}
sec[1][0]=0; //注意此处
for(i=2;i<=n;i++){ //使用前i种硬币凑成j的最小重量
for(j=0;j<=y;j++){
if(j==0){
f[i][j]=0;
sec[i][j]=0;
}
else{
if(f[i-1][j]>=(w[i]+f[i][j-p[i]])&&j-p[i]>=0){
f[i][j]=w[i]+f[i][j-p[i]];
sec[i][j]=i;
}
else{
f[i][j]=f[i-1][j];
sec[i][j]=sec[i-1][j];
}
}
}
}
for(i=n,j=y;i>=1;i--){ //求每种硬币的数量
while(1){
if(sec[i][j]==i){
a[i]++;
j-=p[i];
}
else
break;
}
}
for(i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\n%d",a[n],f[n][y]);
return 0;
}