2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
|
|
@ -1,114 +1,84 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define max_weight 400
|
||||
|
||||
typedef struct { const char *name; int w, v, qty; } item_t;
|
||||
typedef struct {
|
||||
char *name;
|
||||
int weight;
|
||||
int value;
|
||||
int count;
|
||||
} item_t;
|
||||
|
||||
item_t items[] = {
|
||||
{"map", 9, 150, 1},
|
||||
{"compass", 13, 35, 1},
|
||||
{"water", 153, 200, 2},
|
||||
{"sandwich", 50, 60, 2},
|
||||
{"glucose", 15, 60, 2},
|
||||
{"tin", 68, 45, 3},
|
||||
{"banana", 27, 60, 3},
|
||||
{"apple", 39, 40, 3},
|
||||
{"cheese", 23, 30, 1},
|
||||
{"beer", 52, 10, 3},
|
||||
{"suntancream", 11, 70, 1},
|
||||
{"camera", 32, 30, 1},
|
||||
{"T-shirt", 24, 15, 2},
|
||||
{"trousers", 48, 10, 2},
|
||||
{"umbrella", 73, 40, 1},
|
||||
{"w-trousers", 42, 70, 1},
|
||||
{"w-overclothes", 43, 75, 1},
|
||||
{"note-case", 22, 80, 1},
|
||||
{"sunglasses", 7, 20, 1},
|
||||
{"towel", 18, 12, 2},
|
||||
{"socks", 4, 50, 1},
|
||||
{"book", 30, 10, 2},
|
||||
{"map", 9, 150, 1},
|
||||
{"compass", 13, 35, 1},
|
||||
{"water", 153, 200, 2},
|
||||
{"sandwich", 50, 60, 2},
|
||||
{"glucose", 15, 60, 2},
|
||||
{"tin", 68, 45, 3},
|
||||
{"banana", 27, 60, 3},
|
||||
{"apple", 39, 40, 3},
|
||||
{"cheese", 23, 30, 1},
|
||||
{"beer", 52, 10, 3},
|
||||
{"suntan cream", 11, 70, 1},
|
||||
{"camera", 32, 30, 1},
|
||||
{"T-shirt", 24, 15, 2},
|
||||
{"trousers", 48, 10, 2},
|
||||
{"umbrella", 73, 40, 1},
|
||||
{"waterproof trousers", 42, 70, 1},
|
||||
{"waterproof overclothes", 43, 75, 1},
|
||||
{"note-case", 22, 80, 1},
|
||||
{"sunglasses", 7, 20, 1},
|
||||
{"towel", 18, 12, 2},
|
||||
{"socks", 4, 50, 1},
|
||||
{"book", 30, 10, 2},
|
||||
};
|
||||
|
||||
/* for C, the main problem is not the algorithm: it's cache management */
|
||||
#define n_types (sizeof(items)/sizeof(item_t))
|
||||
typedef struct {
|
||||
int v, w; /* value & weight total */
|
||||
unsigned short n[n_types]; /* num of each item taken */
|
||||
} solution_t, *solution;
|
||||
int n = sizeof (items) / sizeof (item_t);
|
||||
|
||||
solution_t *cache, *blank;
|
||||
|
||||
int init_cache()
|
||||
{
|
||||
/* a flat array. If problem size is large, might be a bad idea;
|
||||
* then again, other caching method face similar issue, too
|
||||
*/
|
||||
size_t i;
|
||||
size_t n_rec = (max_weight + 1) * n_types;
|
||||
cache = calloc(sizeof(solution_t), (n_rec + 1));
|
||||
if (!cache) return 0;
|
||||
|
||||
for (i = 0; i <= n_rec; i++) {
|
||||
cache[i].v = -1; /* value = -1 means cache not used yet */
|
||||
cache[i].w = 0;
|
||||
}
|
||||
(blank = cache + n_rec)->v = 0;
|
||||
return 1;
|
||||
int *knapsack (int w) {
|
||||
int i, j, k, v, *mm, **m, *s;
|
||||
mm = calloc((n + 1) * (w + 1), sizeof (int));
|
||||
m = malloc((n + 1) * sizeof (int *));
|
||||
m[0] = mm;
|
||||
for (i = 1; i <= n; i++) {
|
||||
m[i] = &mm[i * (w + 1)];
|
||||
for (j = 0; j <= w; j++) {
|
||||
m[i][j] = m[i - 1][j];
|
||||
for (k = 1; k <= items[i - 1].count; k++) {
|
||||
if (k * items[i - 1].weight > j) {
|
||||
break;
|
||||
}
|
||||
v = m[i - 1][j - k * items[i - 1].weight] + k * items[i - 1].value;
|
||||
if (v > m[i][j]) {
|
||||
m[i][j] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
s = calloc(n, sizeof (int));
|
||||
for (i = n, j = w; i > 0; i--) {
|
||||
int v = m[i][j];
|
||||
for (k = 0; v != m[i - 1][j] + k * items[i - 1].value; k++) {
|
||||
s[i - 1]++;
|
||||
j -= items[i - 1].weight;
|
||||
}
|
||||
}
|
||||
free(mm);
|
||||
free(m);
|
||||
return s;
|
||||
}
|
||||
|
||||
solution solve(int weight, int pos)
|
||||
{
|
||||
int i, w, v, qty;
|
||||
solution sol, best = 0, ret;
|
||||
|
||||
if (pos < 0) return blank;
|
||||
|
||||
ret = &cache[weight * n_types + pos];
|
||||
if (ret->v >= 0) return ret;
|
||||
|
||||
w = items[pos].w;
|
||||
v = items[pos].v;
|
||||
qty = items[pos].qty;
|
||||
|
||||
for (i = 0; i <= qty && weight >= 0; i++, weight -= w) {
|
||||
sol = solve(weight, pos - 1);
|
||||
if (sol->v + i * v <= ret->v) continue;
|
||||
|
||||
best = sol;
|
||||
ret->v = best->v + v * i;
|
||||
ret->n[pos] = i;
|
||||
}
|
||||
|
||||
/* only happens if there are no solution at all, i.e.
|
||||
* max_weight too small to hold even one item
|
||||
*/
|
||||
if (ret->v <= 0) return blank;
|
||||
|
||||
ret->w = best->w + w * ret->n[pos];
|
||||
memcpy(ret->n, best->n, sizeof(unsigned short) * pos);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int i;
|
||||
solution x;
|
||||
|
||||
init_cache();
|
||||
x = solve(max_weight, n_types - 1);
|
||||
|
||||
printf("Taking:\n");
|
||||
for (i = 0; i < n_types; i++) {
|
||||
if (! x->n[i]) continue;
|
||||
printf(" %hu %s\n", x->n[i], items[i].name);
|
||||
}
|
||||
|
||||
printf("Weight: %d Value: %d\n", x->w, x->v);
|
||||
|
||||
/* free(cache); */
|
||||
return 0;
|
||||
int main () {
|
||||
int i, tc = 0, tw = 0, tv = 0, *s;
|
||||
s = knapsack(400);
|
||||
for (i = 0; i < n; i++) {
|
||||
if (s[i]) {
|
||||
printf("%-22s %5d %5d %5d\n", items[i].name, s[i], s[i] * items[i].weight, s[i] * items[i].value);
|
||||
tc += s[i];
|
||||
tw += s[i] * items[i].weight;
|
||||
tv += s[i] * items[i].value;
|
||||
}
|
||||
}
|
||||
printf("%-22s %5d %5d %5d\n", "count, weight, value:", tc, tw, tv);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue