// File: Manca[P]algorithms2/./assignment3.hpp
// Function: assignment3::knapsack_big::knapsack_smallArray(std::vector<int, std::allocator<int>>&, std::vector<int, std::allocator<int>>&, int)
int knapsack_smallArray(std::vector<int>& values, std::vector<int>& weights, const int W)
        {
            // optimized version! (two arrays with at most W+1 elements)
            int *A = new int[W + 1];    // row 1 (current element being processed)
            int *B = new int[W + 1];    // row 0 (previous)
            for (int i = 0; i <= W; i++)
            {
                A[i] = 0;
                B[i] = 0;
            }

            for (size_t i = 1; i <= values.size(); i++)
            {
                for (int x = 1; x <= W; x++)
                {
                    if (weights[i - 1] > x)
                    {
                        A[x] = B[x];
                    }
                    else
                    {
                        A[x] = std::max(B[x], B[x - weights[i - 1]] + values[i - 1]);
                    }
                }

                // interchange only after row is filled (only swap pointers!)
                int* tmp = A;
                A = B;
                B = tmp;
            }

            int res = B[W]; // since the last swap, our final row is in B now
            delete[] A;
            delete[] B;
            return res;

        /**** Version that works too. Only a bit slower.
            //// define and initialize resulting matrix (rows are integral weights up to W (inclusive), so 0,1,2,3...,W, columns are items up to n (inclusive))
            /* std::vector<std::vector<int>> A;    // 2D-array 2x(n+1)
            A.resize(2);
            for (int i = 0; i < 2; i++)
            {
                A[i].resize(W + 1);
            }
            for (size_t i = 1; i <= values.size(); i++)
            {
                for (int x = 1; x <= W; x++)
                {
                    if (weights[i - 1] > x)
                    {
                        A[1][x] = A[0][x];
                    }
                    else
                    {
                        A[1][x] = std::max(A[0][x], A[0][x - weights[i - 1]] + values[i - 1]);
                    }
                }
                // interchange only after row is filled
                for (int x = 1; x <= W; x++)
                {
                    A[0][x] = A[1][x];  // interchange
                }
            }

            return A[1][W]; // bottom right cell contains optimal value
            *****/
        }

// Assembly:
subq $0x88, %rsp
movq %rdi, 0x80(%rsp)
movq %rsi, 0x78(%rsp)
movl %edx, 0x74(%rsp)
movl 0x74(%rsp), %eax
addl $0x1, %eax
cltq
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x3030
movq %rax, 0x68(%rsp)
movl 0x74(%rsp), %eax
addl $0x1, %eax
cltq
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x3030
movq %rax, 0x60(%rsp)
movl $0x0, 0x5c(%rsp)
movl 0x5c(%rsp), %eax
cmpl 0x74(%rsp), %eax
jg 0x7e67
movq 0x68(%rsp), %rax
movslq 0x5c(%rsp), %rcx
movl $0x0, (%rax,%rcx,4)
movq 0x60(%rsp), %rax
movslq 0x5c(%rsp), %rcx
movl $0x0, (%rax,%rcx,4)
movl 0x5c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x5c(%rsp)
jmp 0x7e2e
movq $0x1, 0x50(%rsp)
movq 0x50(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0x80(%rsp), %rdi
callq 0x102a0
movq %rax, %rcx
movq 0x30(%rsp), %rax
cmpq %rcx, %rax
ja 0x7fbf
movl $0x1, 0x4c(%rsp)
movl 0x4c(%rsp), %eax
cmpl 0x74(%rsp), %eax
jg 0x7f8e
movq 0x78(%rsp), %rdi
movq 0x50(%rsp), %rsi
subq $0x1, %rsi
callq 0x11720
movl (%rax), %eax
cmpl 0x4c(%rsp), %eax
jle 0x7ee8
movq 0x60(%rsp), %rax
movslq 0x4c(%rsp), %rcx
movl (%rax,%rcx,4), %edx
movq 0x68(%rsp), %rax
movslq 0x4c(%rsp), %rcx
movl %edx, (%rax,%rcx,4)
jmp 0x7f7c
movq 0x60(%rsp), %rax
movslq 0x4c(%rsp), %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, 0x20(%rsp)
movq 0x60(%rsp), %rax
movq %rax, 0x18(%rsp)
movl 0x4c(%rsp), %eax
movl %eax, 0x14(%rsp)
movq 0x78(%rsp), %rdi
movq 0x50(%rsp), %rsi
subq $0x1, %rsi
callq 0x11720
movl 0x14(%rsp), %ecx
movq %rax, %rdx
movq 0x18(%rsp), %rax
subl (%rdx), %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %eax
movl %eax, 0x2c(%rsp)
movq 0x80(%rsp), %rdi
movq 0x50(%rsp), %rsi
subq $0x1, %rsi
callq 0x11720
movq 0x20(%rsp), %rdi
movq %rax, %rcx
movl 0x2c(%rsp), %eax
addl (%rcx), %eax
movl %eax, 0x48(%rsp)
leaq 0x48(%rsp), %rsi
callq 0x11740
movl (%rax), %edx
movq 0x68(%rsp), %rax
movslq 0x4c(%rsp), %rcx
movl %edx, (%rax,%rcx,4)
jmp 0x7f7e
movl 0x4c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4c(%rsp)
jmp 0x7ea0
movq 0x68(%rsp), %rax
movq %rax, 0x40(%rsp)
movq 0x60(%rsp), %rax
movq %rax, 0x68(%rsp)
movq 0x40(%rsp), %rax
movq %rax, 0x60(%rsp)
movq 0x50(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x50(%rsp)
jmp 0x7e70
movq 0x60(%rsp), %rax
movslq 0x74(%rsp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, 0x3c(%rsp)
movq 0x68(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x7fea
movq 0x8(%rsp), %rdi
callq 0x3320
movq 0x60(%rsp), %rax
movq %rax, (%rsp)
cmpq $0x0, %rax
je 0x8002
movq (%rsp), %rdi
callq 0x3320
movl 0x3c(%rsp), %eax
addq $0x88, %rsp
retq
nop