C++ Knapsack Algorithm Implementation - c++

My algorithm for the best-first, branch and bound knapsack problem is giving me a max profit of 80 when it should be 90. I'm wondering where I went wrong... my thinking is the priority queue is a bit off.
Given input:
4,16 // 4 items to follow , 16 capacity knapsack
2,40 // item1.. weighs 2, costs 40
5,30 // item2.. weighs 5, costs 30
10,50 // item3.. weighs 10, costs 50
5,10 // item4.. weighs 5, costs 10
Code:
#include <iostream>
#include <string>
#include <queue>
#include <utility>
typedef struct node{
int level;
int profit;
int weight;
int bound;
} node;
struct node_cmp{
bool operator()(const node& a, const node& b) const{
return a.bound < b.bound;
}
};
int KWF2(int i, int weight, int profit, int *w, int *p, int C, int n){
int weight1 = weight;
int bound = profit;
int j;
float x[n+1];
for(j = i; j <= n; j++){
x[j] = 0;
}
while(weight1 < C && (i <= n)){
if(weight1 + w[i] <= C){
x[i] = 1;
weight1 += w[i];
bound += p[i];
}
else{
x[i] = ((float)C-(float)weight1)/(float)w[i];
weight1 = C;
bound = bound + p[i] * x[i];
}
i++;
}
return bound;
}
void knapsack(int *w, int *p, int C, int maxprofit, int n){
int maxp = maxprofit;
std::priority_queue<node,std::vector<node>,node_cmp> PQ;
node u,v;
v.level = 0;
v.profit = 0;
v.weight = 0;
v.bound = KWF2(v.level+1,v.weight,v.profit,w,p,C,n);
PQ.push(v);
while(!PQ.empty()){
v = PQ.top();
PQ.pop();
if(v.bound > maxp){
u.level = v.level + 1;
//yes child
u.weight = v.weight + w[u.level];
u.profit = v.profit + p[u.level];
if((u.weight <= C) && (u.profit > maxp)){
maxp = u.profit;
}
if(KWF2(u.level+1,u.weight,u.profit,w,p,C,n) > maxp){
PQ.push(u);
}
//no child
u.weight = v.weight;
u.profit = v.profit;
u.bound = KWF2(u.level+1,u.weight,u.profit,w,p,C,n);
if(u.bound > maxp){
PQ.push(u);
}
}
}
printf("%d\n",maxp);
}
int main(int argc, char **argv){
int n,C;
FILE *in = fopen(argv[1],"r");
fscanf(in,"%d,%d",&n,&C);
int w[n+1];
int p[n+1];
float ratio[n+1];
for(int i = 0; i < n; i++){
fscanf(in,"%d,%d",&w[i+1],&p[i+1]);
ratio[i+1] = (float)p[i+1]/(float)w[i+1];
}
int temp_w,temp_p;
float temp_r;
for(int i = 1; i <= n; i++){
for(int j = i + 1; j <= n; j++){
if(ratio[i] < ratio[j]){
temp_w = w[i];
temp_p = p[i];
temp_r = ratio[i];
w[i] = w[j];
p[i] = p[j];
ratio[i] = ratio[j];
w[j] = temp_w;
p[j] = temp_p;
ratio[j] = ratio[i];
}
}
}
int maxprofit = 0;
knapsack(w,p,C,maxprofit,n);
fclose(in);
return 0;
}

Related

Merge sort errors c++

I'm very new to C++ and only coded in python before, but python is too slow for my purposes now. I did a mergesort algorithm in python and it worked. But now I translated it into C++ and I got a bunch of errors in my IDE. What are my errors?
#include <iostream>
using namespace std;
int *sort(int lenght, int lis[]) {
int units = lenght;
int umt;
int tiles = 1;
while (units > 1) {
bool whole = true;
umt = units % 2;
if (umt = 1) {
units++;
whole = false;
}
units = units / 2;
tiles = tiles * 2;
if (whole) {
int buffd[units];
int add_l = 0;
int add_r = 0;
int prod_l = 0;
int prod_r = prod_l + tiles / 2;
for (int k = 0; k < units; k++) {
int buffd[units];
int add_l = 0;
int add_r = 0;
int prod_l = k * tiles;
int prod_r = prod_l + tiles / 2;
for (int f = 0; f < tiles; f++) {
if (lis[prod_l + add_l] <= lis[prod_r + add_r]) {
buffd[f] = lis[prod_l + add_l];
add_l++;
if (add_l = tiles / 2) {
for (int e = f; e < tiles; e++) {
buffd[e] = lis[prod_r + add_r + e];
}
f = tiles;
}
} else {
buffd[f] = lis[prod_r + add_r];
add_r++;
if (add_r = tiles / 2) {
for (int e = f; e < tiles; e++) {
buffd[e] = lis[prod_l + add_l + e];
}
f = tiles;
}
}
}
for (int i = prod_l; i < prod_l + tiles; i++) {
lis[i] = buffd[i - prod_l];
}
}
} else {
int buffd[units];
int add_l = 0;
int add_r = 0;
int prod_l = 0;
int prod_r = prod_l + tiles / 2;
for (int k = 0; k < units - 1; k++) {
int buffd[units];
int add_l = 0;
int add_r = 0;
int prod_l = k * tiles;
int prod_r = prod_l + tiles / 2;
for (int f = 0; f < tiles; f++) {
if (lis[prod_l + add_l] <= lis[prod_r + add_r]) {
buffd[f] = lis[prod_l + add_l];
add_l++;
if (add_l = tiles / 2) {
for (int e = f; e < tiles; e++) {
buffd[e] = lis[prod_r + add_r + e];
}
f = tiles;
}
} else {
buffd[f] = lis[prod_r + add_r];
add_r++;
if (add_r = tiles / 2) {
for (int e = f; e < tiles; e++) {
buffd[e] = lis[prod_l + add_l + e];
}
f = tiles;
}
}
}
}
for (int i = prod_l; i < prod_l + tiles; i++) {
lis[i] = buffd[i - prod_l];
}
}
}
return lis;
}
int main() {
int to_sort[8] = { 23, 1, 654, 2, 4, 87, 3, 1 };
cout << "sortiert: ";
int *sorted;
sorted = sort(8, to_sort);
for (int p = 0; p < 8; p++) {
cout << sorted[p] << " ";
}
return 0;
}
The errors are in German and I have no idea why, the rest of the IDE is in English. Does anyone know how to set that to English, I'm using Clion from JetBrains.
There are some major problems in your code:
comparisons must use == instead of =, which is the assignment operator.
the redundant definitions for buffd, add_l, add_r, prod_l and prod_r should me removed.
variable length array definitions such as int buffd[units] are not supported by many C++ compilers. These are extensions for compatibility with C90 optional features, likely to cause stack overflow for large arrays. You should allocate these arrays or use std::vector.
these local arrays are declared with a incorrect size: it should be int buffd[tiles];, not int buffd[units]. Undefined behavior ensues.
the last for loop is outside the body of the previous loop, which is incorrect.
you do not increment f before copying the remaining elements from the other slice when either add_l or add_r equals tiles / 2.
your non-recursive algorithm cannot succeed in the general case, I got it to work for array lengths that are powers of 2, and it is quite surprising that it may come as a translation from your python version. There are much simpler ways to program mergesort in python, and in C++ too.
With some extra work, I simplified your code and got it to work for the general case:
#include <iostream>
using namespace std;
int *sort(int length, int lis[]) {
for (int tile = 1; tile < length; tile += tile) {
int tiles = tile + tile;
int *buffd = new int[tiles];
for (int prod_l = 0; prod_l < length; prod_l += tiles) {
int add_l = 0;
int max_l = tile;
int add_r = 0;
int max_r = tile;
int prod_r = prod_l + max_l;
int f = 0;
if (prod_r >= length)
break;
if (prod_r + max_r > length)
max_r = length - prod_r;
for (;;) {
if (lis[prod_l + add_l] <= lis[prod_r + add_r]) {
buffd[f++] = lis[prod_l + add_l++];
if (add_l == max_l) {
while (add_r < max_r) {
buffd[f++] = lis[prod_r + add_r++];
}
break;
}
} else {
buffd[f++] = lis[prod_r + add_r++];
if (add_r == max_r) {
while (add_l < max_l) {
buffd[f++] = lis[prod_l + add_l++];
}
break;
}
}
}
for (int i = 0; i < f; i++) {
lis[prod_l + i] = buffd[i];
}
}
delete[] buffd;
}
return lis;
}
int main() {
int to_sort[8] = { 23, 1, 654, 2, 4, 87, 3, 1 };
for (int i = 1; i < 8; i++) {
cout << "sortiert: ";
int *sorted = sort(i, to_sort);
for (int p = 0; p < i; p++) {
cout << sorted[p] << " ";
}
cout << endl;
}
return 0;
}
Here is a classic top-down recursive implementation for reference:
void mergesort(int lis[], int lo, int hi, int *tmp) {
if (hi - lo >= 2) {
int mid = (hi - lo) / 2;
mergesort(lis, lo, lo + mid, tmp);
mergesort(lis, lo + mid, hi, tmp);
for (int i = 0; i < mid; i++)
tmp[i] = lis[lo + i];
for (int i = 0, j = lo + mid, k = lo; i < mid;) {
if (j >= hi || tmp[i] <= lis[j])
lis[k++] = tmp[i++];
else
lis[k++] = lis[j++];
}
}
}
int *mergesort(int length, int lis[]) {
int *tmp = new int[length / 2];
mergesort(lis, 0, length, tmp);
delete[] tmp;
return lis;
}

Can't find a range of maximum product subarray

I'm solving Maximum Product Subarray problem on C++. My code finds only a max.product of subarray, but not a range.
I found some explanation here - https://www.geeksforgeeks.org/maximum-product-subarray/ and used the code. How could I find the range(Left index, Right index) of subarray that gives me maximum product? (I found some similar posts here, but all of them on java, and i can't understand them properly)
#include<bits/stdc++.h>
#include <stdio.h>
using namespace std;
int min(int x, int y) {
return (x < y) ? x : y;
}
int max(int x, int y) {
return (x > y) ? x : y;
}
int solve(int a[], int n){
int maxend = 0, minend = 0;
int maxans = 0;
for (int i = 1; i <= n; i++){
int temp = maxend;
maxend = max(a[i], max(a[i] * maxend, a[i] * minend));
minend = min(a[i], min(a[i] * temp, a[i] * minend));
maxans = max(maxans, maxend);
}
return maxans;
}
int main(void){
int n, a[10000];
cin >> n;
for(int i=1; i<=n; i++){
cin >> a[i];
}
cout << solve(a, n);
return 0;
}
If all you need is the range information, you can keep track of the indices where maxans variable changed. That would indicate to you where the maximum product comes from, which would be the right endpoint of the range. Then, after you compute the maxans, you can basically go left until you get the maximum product, at which point you will have found the left interval.
The following implementation can serve as a demonstration.
int solve(int a[], int n){
int maxend = 0, minend = 0;
int maxans = 0;
int max_r = -1;
for (int i = 1; i <= n; i++){
int temp = maxend;
maxend = max(a[i], max(a[i] * maxend, a[i] * minend));
minend = min(a[i], min(a[i] * temp, a[i] * minend));
if(maxans < maxend){
maxans = maxend;
max_r = i;
}
}
int max_l = max_r;
for(int i=1; i < maxans; max_l--){
i = i * a[max_l];
}
//At this point you have the range [max_l, max_r] that yield maxans as the product
return maxans;
}

Segmentation fault (core dumped) run time bug with MaxPairwiseProduct program

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int MaxPairwiseProduct(vector<int>& numbers);
//declaration
vector<int> *x;
x->push_back(1);
x->push_back(2);
int answer = MaxPairwiseProduct(*x);
cout << answer;
}
int MaxPairwiseProduct(vector<int>& numbers) {
int index1 = 1;
int index2;
//vector<int> numbers = number;
int n = numbers.size();
for(int i = 2;i < n;++i){
if(numbers[i]>numbers[index1]){
index1 = i;
}
}
if(index1 == 1){
index2 = 2;
} else {
index2 = 1;
}
for(int i = 1;i < n;++i){
if(numbers[i] != numbers[index1] && numbers[i]>numbers[index2]){
index2 = i;
}
}
numbers[index1] * numbers[index2];
return numbers[index1] * numbers[index2];
}
I am trying to implement a seemingly advance algorithm to find the max pair wise product. I continue to get Segmentation fault (core dumped) errors and I know it has something to do with my pointers and scope of my functions perhaps. Any advice or tips?
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int MaxPairwiseProduct(vector<int>& numbers);
//declaration
vector<int> *x = new vector<int>();
x->push_back(7);
x->push_back(4);
x->push_back(5);
x->push_back(6);
int answer = MaxPairwiseProduct(*x);
cout << answer;delete x;
}
int MaxPairwiseProduct(vector<int>& numbers) {
int index1 = 1;
int index2;
//vector<int> numbers = number;
int n = numbers.size();
for(int i = 0;i < n;++i){
if(numbers[i]>numbers[index1]){
index1 = i;
}
}
if(index1 == 1){
index2 = 2;
} else {
index2 = 1;
}
for(int i = 0;i < n;++i){
if(numbers[i] != numbers[index1] && numbers[i]>numbers[index2]){
index2 = i;
}
}
return numbers[index1] * numbers[index2];
}
I got it to work there was an odd late night brain fart.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
long MaxPairwiseProductFast(vector<long>& numbers);
long N, input;
vector<long> *V = new vector<long>();
cin >> N;
do {
V->push_back(input);}
while (V->size() <= N && cin >> input);
long answer = MaxPairwiseProductFast(*V);
cout << answer;
delete V;
}
long MaxPairwiseProductFast(vector<long>& numbers) {
int index1 = 1;
int index2 = 1;
int n = numbers.size();
for(int i = 2;i < n;++i){
if(numbers[i]>numbers[index1]){
index1 = i;
}
}
if(index1 == 1){
index2 = 2;
} else {
index2 = 1;
}
for(int i = 2;i < n;++i){
if(i != index1 && numbers[i]>numbers[index2]){
index2 = i;
}
}
return (long)(numbers[index1] * numbers[index2]);
}
long MaxPairwiseProduct(vector<long>& A) {
int index = 1;
int n = A.size();
for(int i = 2; i < n; ++i){
if (A[i] > A[index]){
index = i;
}
}
swap(A[index], A[n]);
index = 1;
for (int i = 2; i < n-1; ++i){
if(A[i] > A[index]){
index = i;
}
}
swap(A[index], A[n - 1]);
return A[n-1] * A[n];
}
Modified version with user defined size of vector and the ability to define user input values.

Errors Within Void Merge

I've been having problems trying to figure out how to fix this code I wrote for Mergesort.
The intended result was to output a sorted array of inputs, but the void merge function contains errors that result in either an unsorted array or an array of really large or small numbers.
I've tried many times to fix them, but the result still doesn't come out perfectly.
Can you look it over and tell me what I've been doing wrong?
#include "pch.h"
#include <iostream>
using namespace std;
void merge(int* arr, int p, int q, int r) {
//copy A[p.q] into L
//and A[q+1.r] into R
int i, j, k;
int n1 = q - p + 1;
int n2 = r - q;
int* L = new int[n1+1];
int* R = new int[n2+1];
for (i = 1; i <= n1; i++) {
L[i] = arr[p+i-1];
}
for (j = 1; j <= n2; j++){
R[j] = arr[q+j];
}
L[n1+1] = 99999;
R[n2+1] = 99999; //represents infinity
i = j = 1;
for (k = p; k <= r; k++)
{
if (L[i] <= R[j]) {
arr[k] = L[i];
i = i + 1;
}
else {
arr[k] = R[j];
j = j + 1;
}
return;
}
}
void mergesort(int* arr, int p, int r) {
if (p < r) {
int q = floor((p + r) / 2);
mergesort(arr, p, q);
mergesort(arr, q + 1, r);
merge(arr, p, q, r);
}
return;
}
int main() {
int r;
cin >> r;
int* arr = new int[r];
for (int i = 0; i < r; i++) {
int num;
cin >> num;
arr[i] = num;
}
int p = 0;
//sortint function
mergesort(arr,p,r);
for (int i = 0; i < r; i++) {
cout << arr[i] << ";";
}
return 0;
}

mtrix chain multiplication print the sequence of the mattrices

I have written code for matrix chain multiplication in dynamic programming in c++.
there is an error in the recursive call for printing the correct parenthesization of the matrices. I am taking input from text file and giving output on a text file. please help..
#include <iostream>
#include <fstream>
#include <limits.h>
using namespace std;
int * MatrixChainOrder(int p[], int n)
{
static int m[100][100];
static int s[100][100];
int j, q;
int min = INT_MAX;
for (int i = 1; i <= n; i++)
m[i][i] = 0;
for (int L = 2; L <= n; L++) {
for (int i = 1; i <= n - L + 1; i++) {
j = i + L - 1;
m[i][j] = min;
for (int k = i; k <= j - 1; k++) {
q = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
if (q < m[i][j]) {
m[i][j] = q;
s[i][j] = k;
}
}
}
}
return (*s);
}
void Print(int *s, int i, int j)
{
ofstream outfile("output.text");
if (i == j)
{
outfile << "a1";
}
else
outfile << "(";
{
Print(*s, i, s[i][j]);
Print(*s, s[i][j] + 1, j);
outfile << ")";
}
outfile.close();
}
int main()
{
int arr[100];
int num, i = 0;
ifstream infile("input.text");
while (infile)
{
infile >> num;
arr[i] = num;
i++;
}
i = i - 1;
infile.close();
Print(MatrixChainOrder(arr, i - 1), 0, i - 1);
return 0;
}
In C++ it is better to use std::vector for arrays. Aside from that, you can't mix pointers and arrays like that because the compiler loses track of array size.
For example this doesn't work:
int x[10][20];
void foo(int *ptr)
{
//the numbers 10 and 20 have not been passed through
}
But you can change it to
int x[10][20];
void foo(int arr[10][20])
{
//the numbers 10 and 20 are available
}
MatrixChainOrder is supposed to return a number, according to this link
int MatrixChainOrder(int s[100][100], int p[], int n)
{
int m[100][100];
for (int i = 0; i < 100; i++) m[i][i] = 0;
for (int i = 0; i < 100; i++) s[i][i] = 0;
int q = 0;
for (int L = 2; L <= n; L++) {
for (int i = 1; i <= n - L + 1; i++) {
int j = i + L - 1;
m[i][j] = INT_MAX;
for (int k = i; k <= j - 1; k++) {
q = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
if (q < m[i][j]) {
m[i][j] = q;
s[i][j] = k;
}
}
}
}
return q;
}
int main()
{
int arr[] = { 40, 20, 30, 10, 30 };
int array_size = sizeof(arr) / sizeof(int);
int n = array_size - 1;
int s[100][100];
int minimum = MatrixChainOrder(s, arr, n);
printf("{ 40, 20, 30, 10, 30 } should result in 26000 : %d\n", minimum);
return 0;
}
Likewise you can change your Print function
void Print(int s[100][100], int i, int j)
{
if (i < 0 || i >= 100 || j < 0 || j >= 100)
{
cout << "array bound error\n";
}
//safely access s[i][j] ...
}