From aacd9404ae260c0b4f856a803112b582a0f8f253 Mon Sep 17 00:00:00 2001 From: unlockable Date: Mon, 22 Jan 2024 23:45:45 +0100 Subject: [PATCH] 80. --- 2023210/main.cpp | 114 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 82 insertions(+), 32 deletions(-) diff --git a/2023210/main.cpp b/2023210/main.cpp index 3684771..1fe368f 100644 --- a/2023210/main.cpp +++ b/2023210/main.cpp @@ -1,7 +1,7 @@ #include struct CalcResult { - int dim_sizes[32]; + int dim_status; int min_multiply_times; }; @@ -10,84 +10,134 @@ unsigned short *tensors; int n = 0, k = 0; CalcResult *m; // CalcResult m[10000]; -// int * m; +// int* m; +int dim_sizes[32] = {0}; + +int precalc[2][1048576] = {0}; int tensor_pos(int num, int dim) { return k * num + dim; } -int setm(int i, int j, int num, int *dims) { - if (j < i) { +int setm(int i, int j, int num) { + if (j <= i) { return 0; } - m[(2 * n - i + 1) * i / 2 + j - i].min_multiply_times = num; - for (int i = 0; i < k - 2; i++) { - m[(2 * n - i + 1) * i / 2 + j - i].dim_sizes[i] = dims[i]; + return m[(2 * n - i + 1) * i / 2 + j - i].min_multiply_times = num; +} + +int getm(int i, int j) { + if (j <= i) { + return 0; } return m[(2 * n - i + 1) * i / 2 + j - i].min_multiply_times; } -CalcResult getm(int i, int j) { - if (j <= i) { - return CalcResult{{0}, 0}; +int setmdim(int i, int j, int d) { + if (j < i) { + return 0; } - return m[(2 * n - i + 1) * i / 2 + j - i]; + return m[(2 * n - i + 1) * i / 2 + j - i].dim_status = d; } -CalcResult find_min(int start, int end) { - if (start == end || getm(start, end).min_multiply_times != 0) { +int getmdim(int i, int j) { + if (j < i) { + return 0; + } + + return m[(2 * n - i + 1) * i / 2 + j - i].dim_status; +} + +int find_min(int start, int end) { + if (start == end || getm(start, end) != 0) { return getm(start, end); } int min = 2147483647; int needed_multiply_by_d = 1; + int dim_status = getmdim(start, end); // prepare the dims - int segment_dim_size[32] = {0}; - for (int dim = 0; dim < k - 2; dim++) { - for (int tens = start; tens <= end; tens++) { - int d_k = tensors[tensor_pos(tens, dim)]; - if (d_k != 1) { - needed_multiply_by_d *= d_k; - segment_dim_size[dim] = d_k; - break; - } - segment_dim_size[dim] = 1; - } + // for (int i = 0; i < k - 2; i++) { + // if ((dim_status >> i) & 1) { + // needed_multiply_by_d *= dim_sizes[i]; + // } + // } + for (int i = 0; i <= (k - 2) / 16; i++) { + needed_multiply_by_d *= precalc[i][(dim_status >> (16 * i)) & 0xffff]; } for (int split_pos = start; split_pos < end; split_pos++) { - // int a = tensors[tensor_pos(start, k - 2)]; - // a = tensors[tensor_pos(split_pos, k - 1)]; - // a = tensor_pos(end, k - 1); int total_needed = tensors[tensor_pos(start, k - 2)] * tensors[tensor_pos(split_pos, k - 1)] * tensors[tensor_pos(end, k - 1)] * needed_multiply_by_d; - CalcResult left = find_min(start, split_pos), right = find_min(split_pos + 1, end); - total_needed += left.min_multiply_times + right.min_multiply_times; + int left = find_min(start, split_pos), right = find_min(split_pos + 1, end); + total_needed += left + right; if (total_needed < min) { min = total_needed; } } - setm(start, end, min, segment_dim_size); - return getm(start, end); + setm(start, end, min); + return min; +} + +void preparedim(int length) { + if (length == 1) { + for (int i = 0; i < n; i++) { + int cur_stat = 0; + for (int j = 0; j < k - 2; j++) { + if (tensors[tensor_pos(i, j)] != 1) { + cur_stat |= 1 << j; + } + } + setmdim(i, i, cur_stat); + } + return; + } + + preparedim(length - 1); + for (int i = length - 1; i < n; i++) { + setmdim(i - length + 1, i, getmdim(i - length + 1, i - 1) | getmdim(i, i)); + } } int main() { scanf("%d %d", &n, &k); tensors = new unsigned short[n * k]; m = new CalcResult[(n + 1) * n / 2]; + + for (int i = 0; i < 32; i++) { + dim_sizes[i] = 1; + } + // m = new int[(n + 1) * n / 2]; for (int tensor_count = 0; tensor_count < n; tensor_count++) { for (int dim = 0; dim < k; dim++) { scanf("%hu", &tensors[tensor_pos(tensor_count, dim)]); + if (tensors[tensor_pos(tensor_count, dim)] != 1) { + dim_sizes[dim] = tensors[tensor_pos(tensor_count, dim)]; + } } } - printf("%d\n", find_min(0, n - 1).min_multiply_times); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 0xffff; j++) { + int prod = 1; + for (int r = 0; r < 16; r++) { + if ((j >> r) & 1) { + prod *= dim_sizes[i * 16 + r]; + } + } + precalc[i][j] = prod; + } + } + + preparedim(n); + + printf("%d\n", find_min(0, n - 1)); return 0; } \ No newline at end of file