// File: ahnafraihan[P]BestFirstSearch/main.cpp
// Function: knapsack3(int, int*, int*, int, int)
void knapsack3(int n, int p[], int w[], int W, int maxprofit) {
    int optSize = 0; //initialize current optimal size 0
    int numNodes = 1; //initalize current number of nodes visited to 1, to account for root node
    int numLeaves = 0; //initalize current number of leaf nodes visited to 0
    
    //initialize priority queue of nodes Q
    priority_queue<node>Q;
    
    //initialize nodes u and v, with v as root
    node u, v;
    
    //initialize Q to be empty
    v.level = 0; v.profit = 0; v.weight = 0; v.k.resize(n+1, 0); u.k.resize(n+1,0);
    maxprofit = 0; //set current maximum profit to 0
    
    v.bound = bound(n, p, w, W, v);
    Q.push(v); //enqueue v
    
    //remove node with best bound
    while(!Q.empty()){
        v= Q.top();
        Q.pop();
        //expand v to see if it is promising
        if(v.bound > maxprofit) {
            numNodes += 2; //increment number of total nodes visited
            u.level = v.level + 1; // child of v
            //"yes" child
            
            u.weight = v.weight + w[u.level-1];
            u.profit = v.profit + p[u.level-1];
            u.k = v.k; //pass down optimization history to child
            u.k.at(u.level-1) = 1; //designate part of personal solution
            if(u.weight <= W && u.profit > maxprofit) {
                maxprofit = u.profit;
                optimalSolution = u.k; //add to global optimal solution
            }
            
            //find the upper bound of our child u
            u.bound = bound(n, p, w, W, u);
            if(u.bound > maxprofit  && u.weight < W) {
                Q.push(u);
            }
            else
                numLeaves++;
            //"no" child
            
            u.weight = v.weight;
            u.profit = v.profit;
            u.k.at(u.level - 1) = 0;
            u.bound = bound(n, p, w, W, u);
            //node chosen to be expanded
            if(u.bound > maxprofit  && u.weight < W) {
                Q.push(u);
            }
            else
                numLeaves++;
            //node not expanded
        }//queue is empty
        else
            numLeaves++; //increment number of leaf nodes visited
    }
    
    //calculate size of our optimal solution from optimalSolution global variable
    for (int i = 0; i < optimalSolution.size(); i++) {
        if (optimalSolution.at(i) == 1)
            optSize++;
    }
    
    //create output stream to record results onto output text file
    ofstream myfile;
    myfile.open (output.c_str());
    myfile << n << "," << maxprofit << "," << optSize << endl << numNodes << "," << numLeaves << endl;
    for (int i = 0; i < optimalSolution.size(); i++) {
        if (optimalSolution.at(i) == 1)
            myfile << w[i] << "," << p[i] << endl;
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x440, %rsp            # imm = 0x440
movl %edi, -0x4(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
movl %r8d, -0x20(%rbp)
movl $0x0, -0x24(%rbp)
movl $0x1, -0x28(%rbp)
movl $0x0, -0x2c(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x3560
leaq -0x78(%rbp), %rdi
callq 0x3590
leaq -0xa0(%rbp), %rdi
callq 0x3590
movl $0x0, -0xa0(%rbp)
movl $0x0, -0x9c(%rbp)
movl $0x0, -0x98(%rbp)
leaq -0x90(%rbp), %rdi
movl -0x4(%rbp), %eax
incl %eax
movslq %eax, %rsi
movl $0x0, -0xa4(%rbp)
leaq -0xa4(%rbp), %rdx
callq 0x35b0
jmp 0x2c45
leaq -0x68(%rbp), %rdi
movl -0x4(%rbp), %eax
incl %eax
movslq %eax, %rsi
movl $0x0, -0xb8(%rbp)
leaq -0xb8(%rbp), %rdx
callq 0x35b0
jmp 0x2c69
movl $0x0, -0x20(%rbp)
movl -0x4(%rbp), %eax
movl %eax, -0x354(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x350(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x348(%rbp)
movl -0x1c(%rbp), %eax
movl %eax, -0x340(%rbp)
leaq -0xe0(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x3660
jmp 0x2cad
movl -0x340(%rbp), %ecx
movq -0x348(%rbp), %rdx
movq -0x350(%rbp), %rsi
movl -0x354(%rbp), %edi
leaq -0xe0(%rbp), %r8
callq 0x3370
movss %xmm0, -0x358(%rbp)
jmp 0x2cdd
movss -0x358(%rbp), %xmm0
movss %xmm0, -0x94(%rbp)
leaq -0xe0(%rbp), %rdi
callq 0x36a0
leaq -0x50(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x36c0
jmp 0x2d0b
jmp 0x2d0d
leaq -0x50(%rbp), %rdi
callq 0x3710
movb %al, -0x359(%rbp)
jmp 0x2d1e
movb -0x359(%rbp), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x2d2f
jmp 0x3053
leaq -0x50(%rbp), %rdi
callq 0x3730
movq %rax, -0x368(%rbp)
jmp 0x2d41
movq -0x368(%rbp), %rsi
leaq -0xa0(%rbp), %rdi
callq 0x3750
jmp 0x2d56
leaq -0x50(%rbp), %rdi
callq 0x37a0
jmp 0x2d61
movss -0x94(%rbp), %xmm0
cvtsi2ssl -0x20(%rbp), %xmm1
ucomiss %xmm1, %xmm0
jbe 0x3045
movl -0x28(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x28(%rbp)
movl -0xa0(%rbp), %eax
incl %eax
movl %eax, -0x78(%rbp)
movl -0x98(%rbp), %eax
movq -0x18(%rbp), %rcx
movl -0x78(%rbp), %edx
decl %edx
movslq %edx, %rdx
movl (%rcx,%rdx,4), %ecx
addl %ecx, %eax
movl %eax, -0x70(%rbp)
movl -0x9c(%rbp), %eax
movq -0x10(%rbp), %rcx
movl -0x78(%rbp), %edx
decl %edx
movslq %edx, %rdx
movl (%rcx,%rdx,4), %ecx
addl %ecx, %eax
movl %eax, -0x74(%rbp)
leaq -0x90(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0x37f0
jmp 0x2dd1
leaq -0x68(%rbp), %rdi
movl -0x78(%rbp), %eax
decl %eax
movslq %eax, %rsi
callq 0x3a40
movq %rax, -0x370(%rbp)
jmp 0x2deb
movq -0x370(%rbp), %rax
movl $0x1, (%rax)
movl -0x70(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jg 0x2e5c
movl -0x74(%rbp), %eax
cmpl -0x20(%rbp), %eax
jle 0x2e5c
movl -0x74(%rbp), %eax
movl %eax, -0x20(%rbp)
leaq -0x68(%rbp), %rsi
leaq 0xa327(%rip), %rdi      # 0xd140
callq 0x37f0
jmp 0x2e20
jmp 0x2e5c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb0(%rbp)
movl %eax, -0xb4(%rbp)
jmp 0x333c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb0(%rbp)
movl %eax, -0xb4(%rbp)
leaq -0xe0(%rbp), %rdi
callq 0x36a0
jmp 0x333c
movl -0x4(%rbp), %eax
movl %eax, -0x38c(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x388(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x380(%rbp)
movl -0x1c(%rbp), %eax
movl %eax, -0x374(%rbp)
leaq -0x108(%rbp), %rdi
leaq -0x78(%rbp), %rsi
callq 0x3660
jmp 0x2e96
movl -0x374(%rbp), %ecx
movq -0x380(%rbp), %rdx
movq -0x388(%rbp), %rsi
movl -0x38c(%rbp), %edi
leaq -0x108(%rbp), %r8
callq 0x3370
movss %xmm0, -0x390(%rbp)
jmp 0x2ec6
movss -0x390(%rbp), %xmm0
movss %xmm0, -0x6c(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x36a0
movss -0x6c(%rbp), %xmm0
cvtsi2ssl -0x20(%rbp), %xmm1
ucomiss %xmm1, %xmm0
jbe 0x2f2a
movl -0x70(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x2f2a
leaq -0x50(%rbp), %rdi
leaq -0x78(%rbp), %rsi
callq 0x36c0
jmp 0x2f05
jmp 0x2f33
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb0(%rbp)
movl %eax, -0xb4(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x36a0
jmp 0x333c
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
movl -0x98(%rbp), %eax
movl %eax, -0x70(%rbp)
movl -0x9c(%rbp), %eax
movl %eax, -0x74(%rbp)
leaq -0x68(%rbp), %rdi
movl -0x78(%rbp), %eax
decl %eax
movslq %eax, %rsi
callq 0x3a40
movq %rax, -0x398(%rbp)
jmp 0x2f5f
movq -0x398(%rbp), %rax
movl $0x0, (%rax)
movl -0x4(%rbp), %eax
movl %eax, -0x3b4(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x3b0(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x3a8(%rbp)
movl -0x1c(%rbp), %eax
movl %eax, -0x39c(%rbp)
leaq -0x130(%rbp), %rdi
leaq -0x78(%rbp), %rsi
callq 0x3660
jmp 0x2fa6
movl -0x39c(%rbp), %ecx
movq -0x3a8(%rbp), %rdx
movq -0x3b0(%rbp), %rsi
movl -0x3b4(%rbp), %edi
leaq -0x130(%rbp), %r8
callq 0x3370
movss %xmm0, -0x3b8(%rbp)
jmp 0x2fd6
movss -0x3b8(%rbp), %xmm0
movss %xmm0, -0x6c(%rbp)
leaq -0x130(%rbp), %rdi
callq 0x36a0
movss -0x6c(%rbp), %xmm0
cvtsi2ssl -0x20(%rbp), %xmm1
ucomiss %xmm1, %xmm0
jbe 0x303a
movl -0x70(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x303a
leaq -0x50(%rbp), %rdi
leaq -0x78(%rbp), %rsi
callq 0x36c0
jmp 0x3015
jmp 0x3043
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb0(%rbp)
movl %eax, -0xb4(%rbp)
leaq -0x130(%rbp), %rdi
callq 0x36a0
jmp 0x333c
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x304e
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x2d0d
movl $0x0, -0x134(%rbp)
movslq -0x134(%rbp), %rax
movq %rax, -0x3c0(%rbp)
leaq 0xa0ce(%rip), %rdi      # 0xd140
callq 0x3a80
movq %rax, %rcx
movq -0x3c0(%rbp), %rax
cmpq %rcx, %rax
jae 0x30ca
movslq -0x134(%rbp), %rsi
leaq 0xa0ac(%rip), %rdi      # 0xd140
callq 0x3a40
movq %rax, -0x3c8(%rbp)
jmp 0x30a2
movq -0x3c8(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x30b7
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
jmp 0x30b9
movl -0x134(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x134(%rbp)
jmp 0x305d
leaq -0x338(%rbp), %rdi
callq 0x21e0
jmp 0x30d8
leaq 0xa079(%rip), %rdi      # 0xd158
callq 0x2090
movq %rax, %rsi
leaq -0x338(%rbp), %rdi
movl $0x10, %edx
callq 0x2030
jmp 0x30fa
movl -0x4(%rbp), %esi
leaq -0x338(%rbp), %rdi
callq 0x21f0
movq %rax, -0x3d0(%rbp)
jmp 0x3112
movq -0x3d0(%rbp), %rdi
leaq 0x5ee4(%rip), %rsi      # 0x9004
callq 0x2100
movq %rax, -0x3d8(%rbp)
jmp 0x312e
movq -0x3d8(%rbp), %rdi
movl -0x20(%rbp), %esi
callq 0x21f0
movq %rax, -0x3e0(%rbp)
jmp 0x3146
movq -0x3e0(%rbp), %rdi
leaq 0x5eb0(%rip), %rsi      # 0x9004
callq 0x2100
movq %rax, -0x3e8(%rbp)
jmp 0x3162
movq -0x3e8(%rbp), %rdi
movl -0x24(%rbp), %esi
callq 0x21f0
movq %rax, -0x3f0(%rbp)
jmp 0x317a
movq -0x3f0(%rbp), %rdi
movq 0x9e40(%rip), %rsi      # 0xcfc8
callq 0x2130
movq %rax, -0x3f8(%rbp)
jmp 0x3196
movq -0x3f8(%rbp), %rdi
movl -0x28(%rbp), %esi
callq 0x21f0
movq %rax, -0x400(%rbp)
jmp 0x31ae
movq -0x400(%rbp), %rdi
leaq 0x5e48(%rip), %rsi      # 0x9004
callq 0x2100
movq %rax, -0x408(%rbp)
jmp 0x31ca
movq -0x408(%rbp), %rdi
movl -0x2c(%rbp), %esi
callq 0x21f0
movq %rax, -0x410(%rbp)
jmp 0x31e2
movq -0x410(%rbp), %rdi
movq 0x9dd8(%rip), %rsi      # 0xcfc8
callq 0x2130
jmp 0x31f7
movl $0x0, -0x33c(%rbp)
movslq -0x33c(%rbp), %rax
movq %rax, -0x418(%rbp)
leaq 0x9f2a(%rip), %rdi      # 0xd140
callq 0x3a80
movq %rax, %rcx
movq -0x418(%rbp), %rax
cmpq %rcx, %rax
jae 0x3309
movslq -0x33c(%rbp), %rsi
leaq 0x9f04(%rip), %rdi      # 0xd140
callq 0x3a40
movq %rax, -0x420(%rbp)
jmp 0x324a
movq -0x420(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x32f3
movq -0x18(%rbp), %rax
movslq -0x33c(%rbp), %rcx
movl (%rax,%rcx,4), %esi
leaq -0x338(%rbp), %rdi
callq 0x21f0
movq %rax, -0x428(%rbp)
jmp 0x327d
movq -0x428(%rbp), %rdi
leaq 0x5d79(%rip), %rsi      # 0x9004
callq 0x2100
movq %rax, -0x430(%rbp)
jmp 0x3299
movq -0x430(%rbp), %rdi
movq -0x10(%rbp), %rax
movslq -0x33c(%rbp), %rcx
movl (%rax,%rcx,4), %esi
callq 0x21f0
movq %rax, -0x438(%rbp)
jmp 0x32bc
movq -0x438(%rbp), %rdi
movq 0x9cfe(%rip), %rsi      # 0xcfc8
callq 0x2130
jmp 0x32d1
jmp 0x32f3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb0(%rbp)
movl %eax, -0xb4(%rbp)
leaq -0x338(%rbp), %rdi
callq 0x2180
jmp 0x333c
jmp 0x32f5
movl -0x33c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x33c(%rbp)
jmp 0x3201
leaq -0x338(%rbp), %rdi
callq 0x2180
leaq -0xa0(%rbp), %rdi
callq 0x36a0
leaq -0x78(%rbp), %rdi
callq 0x36a0
leaq -0x50(%rbp), %rdi
callq 0x3aa0
addq $0x440, %rsp            # imm = 0x440
popq %rbp
retq
leaq -0xa0(%rbp), %rdi
callq 0x36a0
leaq -0x78(%rbp), %rdi
callq 0x36a0
leaq -0x50(%rbp), %rdi
callq 0x3aa0
movq -0xb0(%rbp), %rdi
callq 0x2200
nopw %cs:(%rax,%rax)