pz12_gavrilov

This is a task for our favourite professor
git clone git://git.stellar-nexus.ru/pz12_gavrilov
Log | Files | Refs

commit 709cc6b9f2baff6339a563620e0eb92183aa6a3c
parent a237bf2f62d1806163676315c60c8867bbcd1f4d
Author: Plat <plat@stellar-nexus.ru>
Date:   Tue, 25 Nov 2025 20:34:42 +0000

Optimized knapsack.c

Diffstat:
Mknapsack.c | 53++++++++++++++++++++++-------------------------------
Mknapsack.h | 18+++++++++++++++---
Mknapsack_single.c | 25++++++++++++++++---------
Msort.c | 2+-
4 files changed, 54 insertions(+), 44 deletions(-)

diff --git a/knapsack.c b/knapsack.c @@ -5,16 +5,18 @@ #include "util.h" int -knapsack_bell(unsigned int k, unsigned int w, int m[k], int c[k], int out[k]) +knapsack_bell(unsigned int k, unsigned int w, + unsigned int m[k], unsigned int c[k], + BitChunk out[k/64+1]) { - int (*opt)[w+1] = malloc(sizeof(*opt) * (k+1)); + unsigned int (*opt)[w+1] = malloc(sizeof(*opt) * (k+1)); if (!opt) { errno = ENOMEM; return -1; } for (unsigned int i = 0; i <= k; ++i) { - for (int wi = 0; wi <= w; ++wi) { + for (unsigned int wi = 0; wi <= w; ++wi) { if (i == 0 || wi == 0) opt[i][wi] = 0; else if (m[i-1] > wi) @@ -28,21 +30,13 @@ knapsack_bell(unsigned int k, unsigned int w, int m[k], int c[k], int out[k]) } } - unsigned int idx = 0; for (; k > 0; --k) { if (opt[k][w] != opt[k-1][w]) { - out[idx++] = k - 1; + SET(out, k - 1); w -= m[k-1]; } } - out[idx] = -1; - for (unsigned int ogidx = --idx, temp; idx > ogidx/2; --idx) { - temp = out[idx]; - out[idx] = out[ogidx-idx]; - out[ogidx-idx] = temp; - } - free(opt); } @@ -50,9 +44,9 @@ static void sift_down(unsigned int n, float a[n], unsigned int idx[n], unsigned int root) { while (1) { - int left = 2 * root + 1; - int right = left + 1; - int largest = root; + unsigned int left = 2 * root + 1; + unsigned int right = left + 1; + unsigned int largest = root; if (left < n && a[left] > a[largest]) largest = left; @@ -99,25 +93,25 @@ extract_max(unsigned int *n, float a[*n], unsigned int idx[*n]) } int -knapsack_greed(unsigned int k, unsigned int w, int m[k], int c[k], int out[k]) +knapsack_greed(unsigned int k, unsigned int w, + unsigned int m[k], unsigned int c[k], + BitChunk out[k/64+1]) { - unsigned int *indices = malloc(sizeof(*indices) * k); float *density = malloc(sizeof(*density) * k); - if (!indices || !density) { + if (!density) { errno = ENOMEM; return -1; } for (unsigned int i = 0; i < k; ++i) { - indices[i] = i; density[i] = (float)c[i]/m[i]; + c[i] = i; /* reuse c array for indices */ } unsigned int heap_size = k; - heap_build(heap_size, density, indices); + heap_build(heap_size, density, c); - unsigned int out_len = 0; unsigned long weight = 0; /* weight can be larger than w - use long */ while (heap_size > 0) { - unsigned int pos = extract_max(&heap_size, density, indices); + unsigned int pos = extract_max(&heap_size, density, c); if (pos == UINT_MAX) break; @@ -125,18 +119,18 @@ knapsack_greed(unsigned int k, unsigned int w, int m[k], int c[k], int out[k]) if (weight > w) weight -= m[pos]; else if (weight < w) - out[out_len++] = pos; + SET(out, pos); else break; } - out[out_len] = -1; - free(indices); free(density); } int -knapsack_full(unsigned int k, unsigned int w, int m[k], int c[k], int out[k]) +knapsack_full(unsigned int k, unsigned int w, + unsigned int m[k], unsigned int c[k], + BitChunk out[k/64+1]) { if (k > sizeof(long)*8) { errno = ERANGE; @@ -156,12 +150,9 @@ knapsack_full(unsigned int k, unsigned int w, int m[k], int c[k], int out[k]) if (cost > best_cost) { best_cost = cost; - unsigned int out_len = 0; - for (unsigned int i = 0; i < k; ++i) { - if (list & (1UL << i)) - out[out_len++] = i; + out[0] = list; /* this function is not used above 64 + - abuse this fact */ } - out[out_len] = -1; } } } diff --git a/knapsack.h b/knapsack.h @@ -1,3 +1,15 @@ -int knapsack_bell(unsigned int k, unsigned int w, int m[k], int c[k], int out[k]); -int knapsack_greed(unsigned int k, unsigned int w, int m[k], int c[k], int out[k]); -int knapsack_full(unsigned int k, unsigned int w, int m[k], int c[k], int out[k]); +#include <stdint.h> +typedef uint64_t BitChunk; +#define CHECK(arr, bit) ((arr)[(bit/64)] & (1ULL << ((bit)%64))) +#define SET(arr, bit) ((arr)[(bit/64)] |= (1ULL << ((bit)%64))) +#define CLEAR(arr, bit) ((arr)[(bit/64)] &= ~(1ULL << ((bit)%64))) + +int knapsack_bell(unsigned int k, unsigned int w, + unsigned int m[k], unsigned int c[k], + BitChunk out[k/64+1]); +int knapsack_greed(unsigned int k, unsigned int w, + unsigned int m[k], unsigned int c[k], + BitChunk out[k/64+1]); +int knapsack_full(unsigned int k, unsigned int w, + unsigned int m[k], unsigned int c[k], + BitChunk out[k/64+1]); diff --git a/knapsack_single.c b/knapsack_single.c @@ -32,24 +32,31 @@ int main(int argc, char *argv[]) { argv0 = argv[0]; - unsigned int k = input(0, UINT_MAX), - w = input(0, UINT_MAX); - int *m = emalloc(sizeof(*m) * k), + unsigned int k = input(0, UINT_MAX); + unsigned int w = input(0, UINT_MAX), + *m = emalloc(sizeof(*m) * k), *c = emalloc(sizeof(*c) * k); unsigned int len; for (len = 0; len < k; ++len) - m[len] = input(0, INT_MAX); + m[len] = input(0, UINT_MAX); for (len = 0; len < k; ++len) - c[len] = input(0, INT_MAX); + c[len] = input(0, UINT_MAX); - int *out = emalloc(sizeof(*out) * k); + BitChunk *out = ecalloc(sizeof(*out) * (k/64 + 1)); clock_t solve_time = clock(); if (knapsack(k, w, m, c, out) < 0) eprintf("knapsack:"); solve_time = clock() - solve_time; printf("%f\n", (double)solve_time / CLOCKS_PER_SEC); - for (len = 0; len + 1 < k && out[len+1] > 0; ++len) - printf("%d ", out[len]); - printf("%d\n", out[len]); + long saved_number = -1; + for (len = 0; len + 1 < k; ++len) { + if (CHECK(out, len)) { + if (saved_number >= 0) + printf("%d ", saved_number); + saved_number = len; + } + } + if (saved_number >= 0) + printf("%d\n", saved_number); } diff --git a/sort.c b/sort.c @@ -15,7 +15,7 @@ bubble_sort(unsigned int n, int a[n]) } void -choice_sort(unsigned int n, int a[n]) /* it's actually insertion_sort :nerd: */ +choice_sort(unsigned int n, int a[n]) /* it's actually selection_sort :nerd: */ { int tmp; for (unsigned int i = 0; i < n - 1; ++i) {