题意:给出一个上限硬币数量s,给出n套硬币价值,求一套硬币能用不大于s数量的硬币组成从1开始连续的区间价值,其中,如果其最大值相同,输出数量小的,如果再相同,输出最大价值小的。
思路:背包。显然要枚举硬币价值。一开始思路是开bool数组记录能否达到,再开used数组记录达到当前总价值的最小所需硬币数量;后来发现只用used一个数组即可。后来参考了另一个人的写法发现还可以优化成完全背包的类似写法。下面贴优化前和后的代码。
#include <stdio.h> #include <string.h> #define INF 0x3fffffff #define N 1005 int n,m,T; int a[15],used[N]; int res[3],out[15];//0表示最优cover值,1表示硬币数量,2表示最大硬币面值 int main(){ //freopen("a.txt","r",stdin); while(scanf("%d",&n) && n){ int i,j,max; res[1] = res[2] = INF; res[0] = 0; scanf("%d",&T); while(T--){ memset(used,0,sizeof(used)); scanf("%d",&m); for(i = 1;i<=m;i++){ scanf("%d",&a[i]); used[a[i]] = 1; } for(i = 1;i<=m;i++) for(j = a[i]+1;j<=n*100;j++){ if(!used[j] && used[j-a[i]] && used[j-a[i]]<n){ used[j] = 1; used[j] = used[j-a[i]]+1; }else if(used[j-a[i]] && used[j-a[i]]<n && used[j-a[i]]+1<used[j]) used[j] = used[j-a[i]]+1; } max = 0; for(i = 1;i<=n*100;i++){ if(!used[i]) break; max++; } if(max>res[0] || (max==res[0]&&m<res[1]) || (max==res[0]&&m==res[1]&&a[m]<res[2])){ res[0] = max; res[1] = m; res[2] = a[m]; for(j = 1;j<=m;j++) out[j] = a[j]; } } printf("max coverage = %d : ",res[0]); for(i = 1;i<=res[1];i++) printf("%d ",out[i]); putchar('\n'); } return 0; }
#include <stdio.h> #include <string.h> #define min(a,b) ((a)<(b)?(a):(b)) #define INF 0x3fffffff #define N 1005 int n,m,T; int a[15],used[N]; int res[3],out[15];//0表示最优cover值,1表示硬币数量,2表示最大硬币面值 int main(){ freopen("a.txt","r",stdin); while(scanf("%d",&n) && n){ int i,j,max; res[1] = res[2] = INF; res[0] = 0; scanf("%d",&T); while(T--){ for(i = 1;i<=100*n;i++) used[i] = n+1; used[0] = 0; scanf("%d",&m); for(i = 1;i<=m;i++) scanf("%d",&a[i]); for(i = 1;i<=m;i++) for(j = a[i];j<=n*100;j++) used[j] = min(used[j],used[j-a[i]]+1); max = 0; for(i = 1;i<=n*100;i++){ if(used[i] == n+1) break; max++; } if(max>res[0] || (max==res[0]&&m<res[1]) || (max==res[0]&&m==res[1]&&a[m]<res[2])){ res[0] = max; res[1] = m; res[2] = a[m]; for(j = 1;j<=m;j++) out[j] = a[j]; } } printf("max coverage = %d : ",res[0]); for(i = 1;i<=res[1];i++) printf("%d ",out[i]); putchar('\n'); } return 0; }