<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">nyoj 995</span>
4 12 10 7 5 1
2
for(int i=1; i<=n; ++i){ scanf("%d",&k); for(int j=k; j<=v; ++j) //小于k的没必要更新 dp[j]=min(dp[j], dp[j-k]+1); }
for(i=1;i<=s;i++) for(j = 0;j<n;j++) { if(i>=mon[j]) { dp[i] = min(dp[i],dp[i-mon[j]]+1); } }
如果不能用这些硬币找零,请给出一种找零方法,使剩下的钱最少,其实就是找 距离它最近的值(该值不为INF),为什么?因为,因为它往前退的过程,就是在找能拼成整的最小硬币的过程.
----------------------------------------------------------------------------------------------------------------------------------------------------------这题易错点 在于 循环控制
WA
while(scanf("%d %d",&n,&s)!=EOF )
其中一个为0就结束循环了,可是题目中可以有一个为0
AC
while(scanf("%d %d",&n,&s) && (n||s) )
#include<stdio.h> #define INF 100000 int mon[55]; int dp[100005]; int main() { int n,s,i,j,count; while(scanf("%d %d",&n,&s) && (n||s) ) { for(i= 0;i<n;i++) scanf("%d",&mon[i]); dp[0]= 0 ; for(i=1;i<=s;i++) dp[i] = INF ; for(i=1;i<=s;i++) for(j = 0;j<n;j++) { if(i>=mon[j]) { dp[i] = dp[i]<dp[i-mon[j]]+1?dp[i]:dp[i-mon[j]]+1; } } for(i = s;i>=0;i--) if(dp[i] !=INF)break; printf("%d\n",dp[i]); } return 0; }
记忆化搜索
#include<stdio.h> #include<string.h> #define INF 100000 int d[100005]; int v[100005]; int n,mon[55]; int dp(int s) { int i,a; if( v[s] == 1)return d[s] ; for(i =0 ;i<n;i++) if(s >= mon[i] && mon[i]!=0) { a = dp(s-mon[i]) +1; d[s] = d[s] <a? d[s]:a; } <pre name="code" class="objc" style="color: rgb(51, 153, 153); font-size: 18px; font-weight: bold;"> v[s] =1;return d[s];}int main(){int s,i,j,k;while(scanf("%d %d",&n,&s) && (n||s) ){ v[0]= 1 ; memset(v,0,sizeof(v)); d[0]= 0 ; for(i=1;i<=s;i++) d[i] = INF ; for(i= 0;i<n;i++) { scanf("%d",&mon[i]); } for(i = 1; i<=s ;i++) { dp(i); } for(i = s;i>=0;i--) if(d[i] !=INF)break;printf("%d\n",d[i]); }return 0;}