poj 3260
地址:http://poj.org/problem?id=3260
题意:有Vi种硬币,每个硬币有Ci个,要付的价钱T,付多了,老板会找钱,用已有的硬币种类找,求给的和找的硬币数量最少的方案。
mark:多重背包,可以参照我的另外一篇日志http://www.cnblogs.com/andre0506/archive/2012/09/22/2697788.html来优化,效率是O(NV)。
这种方法必须排序!
代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct { int v,c; }ss; const int INF = 1000000; const int N = 30000; const int M = 150; int n,t,vmax,cnt; ss s[M]; int d[M*M],dp[N],used[N], min1[N]; int min(int a, int b) {return a < b ? a : b;} int cmp(const void *a, const void *b) { return (*(ss *)b).v - (*(ss *)a).v; } void init() { int i,j; for(i = 1; i < vmax*vmax; d[i++] = INF); d[0] = 0; for(i = 0; i < n; i++) for(j = s[i].v; j < vmax*vmax; j++) d[j] = min(d[j], d[j-s[i].v]+1); } int main() { int i,j,k; while(~scanf("%d%d", &n, &t)) { vmax = 0; for(i = 0; i < n; i++) { scanf("%d", &s[i].v); if(s[i].v > vmax) vmax = s[i].v; } for(i = 0; i < n; i++) scanf("%d", &s[i].c); qsort(s, n, sizeof(ss), cmp); init(); for(i = 1; i < t+vmax*vmax; i++) dp[i] = min1[i] = INF; dp[0] = 0; for(i = 0; i < n; i++) { memset(used, 0, sizeof(used)); for(j = s[i].v; j < t+vmax*vmax; j++) { if(dp[j-s[i].v]+1 < dp[j] && used[j-s[i].v] < s[i].c) { dp[j] = dp[j-s[i].v]+1; used[j] = used[j-s[i].v]+1; if(j >= t && d[j-t] != INF) min1[j] = dp[j]+d[j-t]; } } } cnt = INF; for(i = t; i < t+vmax*vmax; i++) cnt = min(cnt, min1[i]); printf("%d\n", cnt == INF ? -1 : cnt); } return 0; }