ZOJ-2156

来源:互联网 发布:加布.纽维尔 知乎 编辑:程序博客网 时间:2024/05/22 04:51

仍然是多重背包DP,我的算法基本和上题一模一样,但是本题物品比较多,需要组合一下,然后01背包来搞,注意组合物品和DP过程中物品数的累加不要惯性地用加一来DP了。这个在算法在时间上不是最优的,背包九讲上有O(VN)的算法,但我看不大懂,一知半解,就不想去重写了,只好作罢。下次有碰到的话再说吧,我提交的执行时间是150ms,看到排第一的有0ms的,估计用了O(VN)的算法

#include<stdio.h>#include<string.h>static int min(int a, int b){return a < b ? a : b;}static int pack[50], amount[50], tt;static void fill_pack(int total, int cents){int sum = 0, k = 1;while (1){if (sum + k >= total)break;sum += k;pack[tt] = k * cents;amount[tt++] = k;k *= 2;}if (total - sum){pack[tt] = (total - sum) * cents;amount[tt++] = total - sum;}}int main(){int p, c1, c2, c3, c4, dp[10001], path[10001], res[26];while (scanf("%d %d %d %d %d", &p, &c1, &c2, &c3, &c4), p || c1 || c2 || c3|| c4){c1 = min(p, c1), c2 = min(p / 5, c2), c3 = min(p / 10, c3), c4 = min(p / 25, c4);tt = 0;fill_pack(c1, 1);fill_pack(c2, 5);fill_pack(c3, 10);fill_pack(c4, 25);int i, j;dp[0] = 0;for (i = 1; i <= p; i++)dp[i] = -1;for (i = 0; i < tt; i++)for (j = p; j >= pack[i]; j--)if (dp[j - pack[i]] != -1&& dp[j - pack[i]] + amount[i] > dp[j]){dp[j] = dp[j - pack[i]] + amount[i];path[j] = i;}if (dp[p] != -1){memset(res, 0, sizeof(res));while (p){int ii = path[p];res[pack[ii] / amount[ii]] += amount[ii];p -= pack[ii];}printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n",res[1], res[5], res[10], res[25]);}elseputs("Charlie cannot buy coffee.");}return 0;}


0 0
原创粉丝点击