I was playing with Knight Tour algorithm implementation in Java. All that time I was completely sure that implementation on C must be faster. So after reading GNU C Reference the code be done and logic was implemented the same way is on Java.
Can you imagine my wonder when the C variant took more time to process a 6x6 board.
So my question is how the code below can be optimized from technical perspective (i.e. without heuristic optimizations).
Some performance notes: on my i5 laptop with Ubuntu the provided implementation took more than 4 hours to solve 6x6 board. Program on Java can solve this task in about 3 hours 18 mins with single threaded approach.
Some algorithm notes: this implementation finds all possible tours from all cells on the board, not just closed tours. As well heuristic optimization isn't used as it helps to find faster first tour not all.
EDIT: code compiled without any optimization with this command: gcc knight_tour.c -o knight-tour
#include "stdio.h"
#define BOARD_SIZE 5
#define MAX_MOVE_COUNT BOARD_SIZE*BOARD_SIZE
void printBoard(int[][BOARD_SIZE], int);
void clearBoard(int[][BOARD_SIZE], int);
int knight_move(int[][BOARD_SIZE], int, int, int);
int is_valid_position(int, int);
void calc_all_knight_jumps();
static int ALL_KNIGHT_COL_JUMPS[BOARD_SIZE][BOARD_SIZE][9];
static int ALL_KNIGHT_ROW_JUMPS[BOARD_SIZE][BOARD_SIZE][8];
int main() {
int board[BOARD_SIZE][BOARD_SIZE];
clearBoard(board, BOARD_SIZE);
calc_all_knight_jumps();
int result[BOARD_SIZE][BOARD_SIZE];
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
result[i][j] = knight_move(board, i, j, 1);
}
}
printBoard(result, BOARD_SIZE);
return 0;
}
int knight_move(int board[][BOARD_SIZE], int cpos, int rpos, int level) {
if (level == MAX_MOVE_COUNT)
return 1;
board[cpos][rpos] = level;
int solved_count = 0;
int jump_count = ALL_KNIGHT_COL_JUMPS[cpos][rpos][8];
for (int i = 0; i < jump_count; i++) {
int next_cpos = ALL_KNIGHT_COL_JUMPS[cpos][rpos][i];
int next_rpos = ALL_KNIGHT_ROW_JUMPS[cpos][rpos][i];
if (board[next_cpos][next_rpos] == 0) {
solved_count += knight_move(board, next_cpos, next_rpos, level + 1);
}
}
board[cpos][rpos] = 0;
return solved_count;
}
void clearBoard(int board[][BOARD_SIZE], int size) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
board[i][j] = 0;
}
}
}
void printBoard(int board[][BOARD_SIZE], int size) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
printf("%8d", board[i][j]);
}
printf("\n");
}
}
int is_valid_position(int cpos, int rpos) {
if (cpos < 0 || cpos >= BOARD_SIZE) return 0;
if (rpos < 0 || rpos >= BOARD_SIZE) return 0;
return 1;
}
void calc_all_knight_jumps() {
int col_jumps[] = { 1, 2, 2, 1, -1, -2, -2, -1};
int row_jumps[] = { 2, 1, -1, -2, -2, -1, 1, 2};
int next_cpos, next_rpos;
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
int jump_count = 0;
for (int k = 0; k < 8; k++) {
next_cpos = i + col_jumps[k];
next_rpos = j + row_jumps[k];
if (is_valid_position(next_cpos, next_rpos) == 1) {
ALL_KNIGHT_COL_JUMPS[i][j][jump_count] = next_cpos;
ALL_KNIGHT_ROW_JUMPS[i][j][jump_count] = next_rpos;
jump_count++;
}
}
ALL_KNIGHT_COL_JUMPS[i][j][8] = jump_count;
}
}
}
Taking into account all the comments I modified the source code a bit.
tried out -O2 and -O3 optimization options with gcc compiler;
reduced number of top level invocation on knight_move() method. so now only unique results are calculated and then reflected horizontally, vertically and diagonally;
added code to measure performance without printf() usage;
checked that both C and Java variants are identical as much as possible;
And finally there are results I expected - C code is faster (but with optimization options)
C code with the -O2 option: duration - 1348 sec (22:28)
Java code: duration - 1995 sec (33:15)
C code without optimization: duration - 3518 sec (58:38)
C code with the -O3 option: duration - 2143 sec (35:43)
Here are both implementations in case someone be interested in knight tour algorithm on C and Java:-)
GNU C
#include "stdio.h"
#include "time.h"
#define BOARD_SIZE 6
#define MAX_MOVE_COUNT BOARD_SIZE*BOARD_SIZE
int knight_move(int[][BOARD_SIZE], int, int, int);
void pre_calc_all_knight_jumps();
void print_result(int[][BOARD_SIZE]);
static int ALL_KNIGHT_COL_JUMPS[BOARD_SIZE][BOARD_SIZE][9];
static int ALL_KNIGHT_ROW_JUMPS[BOARD_SIZE][BOARD_SIZE][8];
int main() {
// init board
int board[BOARD_SIZE][BOARD_SIZE];
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
board[i][j] = 0;
}
}
pre_calc_all_knight_jumps();
int result[BOARD_SIZE][BOARD_SIZE];
struct timespec s_time, e_time;
clock_gettime(CLOCK_MONOTONIC, &s_time);
int border = BOARD_SIZE - 1;
int center = BOARD_SIZE / 2.0 + 0.5;
for (int i = 0; i < center; i++) {
for (int j = i; j < center; j++) {
int res = knight_move(board, i, j, 1);
result[i][j] = res;
result[border - i][j] = res;
result[i][border - j] = res;
result[border - i][border - j] = res;
if (i != j) result[j][i] = res;
}
}
clock_gettime(CLOCK_MONOTONIC, &e_time);
printf("Duration in seconds: %ld\n", e_time.tv_sec - s_time.tv_sec);
print_result(result);
return 0;
}
int knight_move(int board[][BOARD_SIZE], int cpos, int rpos, int level) {
if (level == MAX_MOVE_COUNT) return 1;
board[cpos][rpos] = level;
int solved_count = 0;
int valid_move_count = ALL_KNIGHT_COL_JUMPS[cpos][rpos][8];
for (int i = 0; i < valid_move_count; i++) {
int next_cpos = ALL_KNIGHT_COL_JUMPS[cpos][rpos][i];
int next_rpos = ALL_KNIGHT_ROW_JUMPS[cpos][rpos][i];
if (board[next_cpos][next_rpos] == 0) {
solved_count += knight_move(board, next_cpos, next_rpos, level + 1);
}
}
board[cpos][rpos] = 0;
return solved_count;
}
void print_result(int board[][BOARD_SIZE]) {
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
printf("%8d", board[i][j]);
}
printf("\n");
}
}
void pre_calc_all_knight_jumps() {
int col_jumps[] = { 1, 2, 2, 1, -1, -2, -2, -1};
int row_jumps[] = { 2, 1, -1, -2, -2, -1, 1, 2};
int next_cpos, next_rpos;
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
int jump_count = 0;
for (int k = 0; k < 8; k++) {
next_cpos = i + col_jumps[k];
next_rpos = j + row_jumps[k];
if (next_cpos < 0 || next_cpos >= BOARD_SIZE) continue;
if (next_rpos < 0 || next_rpos >= BOARD_SIZE) continue;
ALL_KNIGHT_COL_JUMPS[i][j][jump_count] = next_cpos;
ALL_KNIGHT_ROW_JUMPS[i][j][jump_count] = next_rpos;
jump_count++;
}
ALL_KNIGHT_COL_JUMPS[i][j][8] = jump_count;
}
}
}
Java
import java.util.Arrays;
public class KnightTour1 {
private final static int BOARD_SIZE = 6;
private final static int MAX_MOVE_COUNT = BOARD_SIZE * BOARD_SIZE;
private static final int[][][] ALL_KNIGHT_COL_MOVES;
private static final int[][][] ALL_KNIGHT_ROW_MOVES;
static {
final int[] knightColJumps = { 1, 2, 2, 1, -1, -2, -2, -1};
final int[] knightRowJumps = { 2, 1, -1, -2, -2, -1, 1, 2};
ALL_KNIGHT_COL_MOVES = new int[BOARD_SIZE][BOARD_SIZE][];
ALL_KNIGHT_ROW_MOVES = new int[BOARD_SIZE][BOARD_SIZE][];
int[] tmpColMoves = new int[8];
int[] tmpRowMoves = new int[8];
for (int c = 0; c < BOARD_SIZE; c++) {
for (int r = 0; r < BOARD_SIZE; r++) {
int jumpCount = 0;
for (int i = 0; i < 8; i++) {
int nextColPos = c + knightColJumps[i];
int nextRowPos = r + knightRowJumps[i];
if (isValidBoardPos(nextColPos, nextRowPos)) {
tmpColMoves[jumpCount] = nextColPos;
tmpRowMoves[jumpCount] = nextRowPos;
jumpCount++;
}
}
ALL_KNIGHT_COL_MOVES[c][r] = Arrays.copyOf(tmpColMoves, jumpCount);
ALL_KNIGHT_ROW_MOVES[c][r] = Arrays.copyOf(tmpRowMoves, jumpCount);
}
}
}
private static boolean isValidBoardPos(int colPos, int rowPos) {
return colPos > -1 && colPos < BOARD_SIZE && rowPos > -1 && rowPos < BOARD_SIZE;
}
public static void main(String[] args) {
long sTime = System.currentTimeMillis();
int[][] result = findNumberOfTours();
long duration = (System.currentTimeMillis() - sTime) / 1000;
System.out.println("Duration in seconds: " + duration);
printResult(result);
}
private static int knightMove(int[][] board, int colPos, int rowPos, int level) {
if (level == MAX_MOVE_COUNT) return 1;
board[colPos][rowPos] = level;
final int[] validColMoves = ALL_KNIGHT_COL_MOVES[colPos][rowPos];
final int[] validRowMoves = ALL_KNIGHT_ROW_MOVES[colPos][rowPos];
final int validMoveCount = validColMoves.length;
int solvedTourCount = 0;
for (int i = 0; i < validMoveCount; i++) {
final int nextColPos = validColMoves[i];
final int nextRowPos = validRowMoves[i];
if (board[nextColPos][nextRowPos] == 0) {
solvedTourCount += knightMove(board, nextColPos, nextRowPos, level + 1);
}
}
board[colPos][rowPos] = 0;
return solvedTourCount;
}
private static int[][] findNumberOfTours() {
final int[][] result = new int[BOARD_SIZE][BOARD_SIZE];
final int[][] board = new int[BOARD_SIZE][BOARD_SIZE];
final int border = BOARD_SIZE - 1;
final int center = (int)(BOARD_SIZE / 2f + 0.5);
for (int i = 0; i < center; i++) {
for (int j = i; j < center; j++) {
int res = knightMove(board, i, j, 1);
result[i][j] = res;
result[border - i][j] = res;
result[i][border - j] = res;
result[border - i][border - j] = res;
if (i != j) result[j][i] = res;
}
}
return result;
}
private static void printResult(int[][] res) {
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
System.out.print(String.format("%8d", res[i][j]));
}
System.out.println();
}
}
}
Here are some suggestions about your code as well as the updated version posted in your answer:
use <> for standard header files:
#include <stdio.h>
surround expressions with parentheses in macro definitions:
#define MAX_MOVE_COUNT (BOARD_SIZE * BOARD_SIZE)
use (void) when declaring functions without arguments:
void pre_calc_all_knight_jumps(void);
avoid mixing floating point and integer calculations with implicit conversions. Use this instead:
int center = (BOARD_SIZE + 1) / 2;
Some of the symmetries are not properly reflected in the result array. You should change the main loop to:
int border = BOARD_SIZE - 1;
int center = (BOARD_SIZE + 1) / 2;
for (int i = 0; i < center; i++) {
for (int j = i; j < center; j++) {
int res = knight_move(board, i, j, 1);
result[i][j] = res;
result[j][i] = res;
result[border - i][j] = res;
result[j][border - i] = res;
result[i][border - j] = res;
result[border - j][i] = res;
result[border - i][border - j] = res;
result[border - j][border - i] = res;
}
}
I also get some cache usage improvements by making the board 8x8 and using a additional argument for the playing area size.
A more efficient algorithm is definitely needed to solve this problem for larger sizes.
Related
This is the question:
https://www.hackerrank.com/challenges/lisa-workbook/problem.
My code passes all the test cases except one. The message I get is just Run Time Error. Even if I return 0 at the beginning of the function that I am supposed to implement, I still get this error, while in all other test cases I get Wrong Answer.
This is not the only question on hacker rank where this happened. In the last couple of days I encountered 3 or 4 more questions with that one odd case that was always giving a runtime error. In the end, I had to implement a Python 3 solution (with the same logic), which passed all the test cases, to solve these problems.
I wonder if this is a bug on the website or if I am understanding something wrongly. Here is my function implementation for this problem:
int workbook(int n, int k, int arr_count, int* arr)
{
int tmp = 1, specprob = 0;
int *chstart = malloc(n * sizeof(int));
int *chend = malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
chstart[i] = tmp;
tmp += arr[i] / k - 1;
if (arr[i] % k != 0) {
tmp++;
}
chend[i] = tmp;
tmp++;
if (!(arr[i] < chstart[i])) {
int qno = 0, chpage = 1, iqno = 0;
for (int j = chstart[i]; j < chend[i] + 1; j++) {
if (chpage * k <= arr[i]) {
qno += k;
} else {
qno += (k - (chpage * k - arr[i]));
}
if (j > iqno && j < qno + 1) {
specprob++;
}
iqno = qno;
chpage++;
}
}
}
return specprob;
}
It looks like a bug, since when you run the empty function with just a return 0; it gives the same runtime error.
For the moment though, if you don't mind too much about the different language, you could make a few minor changes to the code to make it compile for C++ (don't forget to change the language selection too):
int workbook(int n, int k, vector<int> arr)
{
int tmp = 1, specprob = 0;
int *chstart = (int*)malloc(n * sizeof(int));
int *chend = (int*)malloc(n * sizeof(int));
for (int i = 0; i < n; i++)
{
chstart[i] = tmp;
tmp += arr[i] / k - 1;
if (arr[i] % k != 0)
{
tmp++;
}
chend[i] = tmp;
tmp++;
if (!(arr[i] < chstart[i]))
{
int qno = 0, chpage = 1, iqno = 0;
for (int j = chstart[i]; j < chend[i] + 1; j++)
{
if (chpage * k <= arr[i])
{
qno += k;
}
else
{
qno += (k - (chpage * k - arr[i]));
}
if (j > iqno && j < qno + 1)
{
specprob++;
}
iqno = qno;
chpage++;
}
}
}
return specprob;
}
I have a problem with making from the sequential algorithm parallel one with task parallelism.
My problem is the Minimum Cut of a Graph and in sequential case, I can achieve the correct result.
Here is part of my code:
main.c
struct ProblemInstance instance = readFromFile(file);
bool *solution = malloc(sizeof(bool) * vertexCount);
for (int n = 0; n < vertexCount; n++)
solution[n] = false;
#pragma omp parallel num_threads(2)
{
printf("Number of thread: %d \n", omp_get_thread_num());
#pragma omp single
recursiveBruteForce(solution, 0, 0);
}
problem.c
void recursiveBruteForce(bool *solution, float cutSum, int depth) {
// In case if it is not correct
if (checkPartialSolution(solution, depth)) return;
if (cutSum > minCutValue) return;
if (depth == vertexCount) {
minCutValue = cutSum;
for (int i = 0; i < vertexCount; i++)
minCutArray[i] = solution[i];
return;
}
solution[depth] = false;
#pragma omp task
recursiveBruteForce(solution, minCutSum(solution, depth + 1), depth + 1);
solution[depth] = true;
#pragma omp task
recursiveBruteForce(solution, minCutSum(solution, depth + 1), depth + 1);
}
// Check Particular Solution to how many 1 and 0 have
bool checkPartialSolution(const bool *solution, int depth) {
int a = 0, n = 0;
for (int i = 0; i < depth; i++) {
if (solution[i])
a = a + 1;
else
n = n + 1;
if (a > subgroupSize || n > (vertexCount - subgroupSize))
return true;
}
return false;
}
// Get a sum of Sub-Graph
double minCutSum(const bool *solution, int depth) {
float sum = 0;
for (int i = 0; i < depth; i++) {
for (int j = 0; j < i; j++) {
if (solution[j] != solution[i])
sum += graphConnections[j][i];
}
}
return sum;
}
I have tried to look at how many calls did recursiveBruteForce function. In sequential, it is approximately 22,000, while in parallel 62. I think the problem with memory.
Any suggestions?
Task description -> Whole task description is here
I have done part with sorting and got stuck.
How can I combine these arrays in one of already sorted pairs?
printf("\nHeight of boys in descending order\n");
for (i = (LENGTH1 - 1); i >= 0; i--)
{
printf("%d ", heightBoys[i]);
}
for (i = 0; i < LENGTH2; i++)
{
for (j = 0; j < (LENGTH2 - j - 1); j++)
{
if (heightGirls[j] > heightGirls[j+1])
{
temp = heightGirls[j];
heightGirls[j] = heightGirls[j+1];
heightGirls[j+1] = temp;
}
}
}
printf("\nHeight of girls in descending order\n");
for (j = (LENGTH2 - 1); j >= 0; j--)
{
printf("%d ", heightGirls[j]);
}
You have a sort [for the girls], but it is broken. Change:
for (j = 0; j < (LENGTH2 - j - 1); j++)
Into:
for (j = 0; j < (LENGTH2 - i - 1); j++)
To avoid [needless] replication of code, put the sorting code into a separate function.
Sort both arrays.
Take the minimum of the lengths of the two arrays (e.g. minlen).
I'm not sure what you mean [exactly] by "pairing", but the simplest is to print the pairing
Then, just loop on:
for (i = 0; i < minlen; ++i)
printf("Girl:%d Boy:%d\n",heightGirls[i],heightBoys[i]);
If you needed something more complex, you might need an array of structs like:
struct pair {
int boyheight;
int girlheight;
};
This array would need to be at least minlen in length. You could fill it in by adapting the final print loop.
But, if you're just printing, here is some sample code:
#include <stdio.h>
void
print_single(const int *height,int len,const char *sex)
{
printf("\nHeight of %s in descending order\n",sex);
for (int i = (len - 1); i >= 0; i--)
printf(" %d", height[i]);
printf("\n");
}
void
sort_height(int *height,int len)
{
for (int i = 0; i < len; i++) {
for (int j = 0; j < (len - i - 1); j++) {
if (height[j] > height[j + 1]) {
int temp = height[j];
height[j] = height[j + 1];
height[j + 1] = temp;
}
}
}
}
int
main(void)
{
int heightBoys[] = { 5, 8, 7, 9, 6 };
int heightGirls[] = { 3, 1, 2 };
int LENGTH1 = sizeof(heightBoys) / sizeof(heightBoys[0]);
int LENGTH2 = sizeof(heightGirls) / sizeof(heightGirls[0]);
sort_height(heightBoys,LENGTH1);
print_single(heightBoys,LENGTH1,"boys");
sort_height(heightGirls,LENGTH2);
print_single(heightGirls,LENGTH2,"girls");
int minlen = LENGTH1;
if (minlen > LENGTH2)
minlen = LENGTH2;
printf("\n");
printf("Pairing:\n");
for (int i = 0; i < minlen; ++i)
printf("Girl:%d Boy:%d\n",heightGirls[i],heightBoys[i]);
return 0;
}
UPDATE:
Let's say that we input heights and number of them by ourselves. If we have extra heights of boys or girls, how can we output these extra heights apart from the rest?
Two additional for loops appended to the bottom should do the trick. In order for this to work, the iteration variable of the final for loop in the previous example must be defined outside the loop. In other words, notice the definition and usage of ipair below.
If you are creating an array the type of struct that I suggested, these loops can fill it in. The array size would then need to be max(LENGTH1,LENGTH2).
And, in unpaired loops (e.g. for boy 8, the girl value in the struct could be set to 0 or -1 to indicate that the boy is unpaired)
#include <stdio.h>
void
print_single(const int *height,int len,const char *sex)
{
printf("\nHeight of %s in descending order\n",sex);
for (int i = (len - 1); i >= 0; i--)
printf(" %d", height[i]);
printf("\n");
}
void
sort_height(int *height,int len)
{
for (int i = 0; i < len; i++) {
for (int j = 0; j < (len - i - 1); j++) {
if (height[j] > height[j + 1]) {
int temp = height[j];
height[j] = height[j + 1];
height[j + 1] = temp;
}
}
}
}
int
main(void)
{
int heightBoys[] = { 5, 8, 7, 9, 6 };
int heightGirls[] = { 3, 1, 2 };
int LENGTH1 = sizeof(heightBoys) / sizeof(heightBoys[0]);
int LENGTH2 = sizeof(heightGirls) / sizeof(heightGirls[0]);
sort_height(heightBoys,LENGTH1);
print_single(heightBoys,LENGTH1,"boys");
sort_height(heightGirls,LENGTH2);
print_single(heightGirls,LENGTH2,"girls");
int minlen = LENGTH1;
if (minlen > LENGTH2)
minlen = LENGTH2;
int ipair = 0;
printf("\n");
printf("Pairing:\n");
for (; ipair < minlen; ++ipair)
printf("Girl:%d Boy:%d\n",heightGirls[ipair],heightBoys[ipair]);
if (ipair < LENGTH1) {
printf("\n");
printf("Unpaired Boys:\n");
for (int i = ipair; i < LENGTH1; ++i)
printf("Boy:%d\n",heightBoys[i]);
}
if (ipair < LENGTH2) {
printf("\n");
printf("Unpaired Girls:\n");
for (int i = ipair; i < LENGTH2; ++i)
printf("Girl:%d\n",heightGirls[i]);
}
return 0;
}
This is my code for Project Euler: Problem 11
int main(int argc, char** argv) {
char stevila [1600] = "08022297381500400075040507785212507791084949994017811857608717409843694804566200814931735579142993714067538830034913366552709523046011426924685601325671370236912231167151676389419236542240402866331380244732609903450244753353783684203517125032988128642367102638406759547066183864706726206802621220956394396308409166499421245558056673992697177878968314883489637221362309750076442045351400613397343133957817532822753167159403800462161409535692163905429635314755588824001754243629855786560048357189070544443744602158515417581980816805944769287392138652177704895540045208839735991607975732162626793327986688366887576220720346336746551232639353690442167338253911249472180846293240627636206936417230238834629969826759857404361620733529783190017431497148868116235705540170547183515469169233486143520189196748";
int stevilaGrid [20][20];
int stevilaRacunanje[4][4];
int stevecPoStevilih = 0;
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 20; j++) {
stevilaGrid[i][j] = (stevila[stevecPoStevilih] - 48)*10 + stevila[stevecPoStevilih + 1] - 48;
stevecPoStevilih += 2;
}
}
int rezultat [10];
int najvecji = 0;
int trenutni;
int temp = 0;
for (int i = 0; i < 17; i++) {
for (int j = 0; j < 17; j++) {
//problems start here
for (int k = 0; k < 5; k++) {
for (int l = 0; l < 5; l++) {
temp = stevilaGrid[i + k][j + l];
stevilaRacunanje[k][l] = temp;
}
}
for (int k = 0; k < 5; k++) {
rezultat[k] = stevilaRacunanje[k][0] * stevilaRacunanje[k][1] * stevilaRacunanje[k][2] * stevilaRacunanje[k][3];
rezultat[k+4] = stevilaRacunanje[0][k] * stevilaRacunanje[1][k] * stevilaRacunanje[2][k] * stevilaRacunanje[3][k];
}
rezultat[8] = stevilaRacunanje[0][0] * stevilaRacunanje[1][1] * stevilaRacunanje[2][2] * stevilaRacunanje[3][3];
rezultat[9] = stevilaRacunanje[0][3] * stevilaRacunanje[1][2] * stevilaRacunanje[2][1] * stevilaRacunanje[3][0];
for (int k = 0; k < 10; k++) {
trenutni = rezultat[k];
if(trenutni > najvecji){
najvecji = trenutni;
}
}
}
}
printf("Najvecji zmnozek: %d", najvecji);
return (EXIT_SUCCESS);
}
First I convert the string of numbers into a 2D int array.
Then I try to divide the grid into smaller 4x4 squares with which I can work more easily. That is where the problems start (as marked in the code).
At the very beginning (*i=0,j=0;k=4,j=0*) something strange starts to happen. The values in *stevilaGrid[][]* start to change randomly and seemingly without a reason.
Can somebody please explain this to me. I have tested this behavior on Windows with Cygwin 64bit and Ubuntu with GCC 64bit.
[i + k][j + l];
When i==16 and k==4 or j==16 and j==4 you'll be hitting element [20]
Your array only goes 0...19
I want to solve the knapsack problem with dynamic programming! The item should be in the knapsack or not, I do not want to put the same item in the knapsack more then one time!
I've looked at this code but with this one you can add the same object more then just one time
#include <stdio.h>
#define MAXWEIGHT 100
int n = 3; /* The number of objects */
int c[10] = {8, 6, 4}; /* c[i] is the *COST* of the ith object; i.e. what
YOU PAY to take the object */
int v[10] = {16, 10, 7}; /* v[i] is the *VALUE* of the ith object; i.e.
what YOU GET for taking the object */
int W = 10; /* The maximum weight you can take */
void fill_sack() {
int a[MAXWEIGHT]; /* a[i] holds the maximum value that can be obtained
using at most i weight */
int last_added[MAXWEIGHT]; /* I use this to calculate which object were
added */
int i, j;
int aux;
for (i = 0; i <= W; ++i) {
a[i] = 0;
last_added[i] = -1;
}
a[0] = 0;
for (i = 1; i <= W; ++i)
for (j = 0; j < n; ++j)
if ((c[j] <= i) && (a[i] < a[i - c[j]] + v[j])) {
a[i] = a[i - c[j]] + v[j];
last_added[i] = j;
}
for (i = 0; i <= W; ++i)
if (last_added[i] != -1)
printf("Weight %d; Benefit: %d; To reach this weight I added object %d (%d$ %dKg) to weight %d.\n",
i, a[i], last_added[i] + 1, v[last_added[i]],
c[last_added[i]], i - c[last_added[i]]);
else
printf("Weight %d; Benefit: 0; Can't reach this exact weight.\n", i);
printf("---\n");
aux = W;
while ((aux > 0) && (last_added[aux] != -1)) {
printf("Added object %d (%d$ %dKg). Space left: %d\n",
last_added[aux] + 1, v[last_added[aux]],
c[last_added[aux]], aux - c[last_added[aux]]);
aux -= c[last_added[aux]];
}
printf("Total value added: %d$\n", a[W]);
}
int main(int argc, char *argv[]) {
fill_sack();
return 0;
}
and then i tried to make a array to see if the object is in the knapsack or not, but then this program did not work as it should!
#define MAXWEIGHT 101
#define MAX_ITEMS 100000
int items = 2;
int c[10] = {1, 2};
int v[10] = {1000, 2001};
int W = 100;
int taken[MAX_ITEMS];
void takenOrNot(){
int i;
for(i = 0; i < items; i++){
taken[i] = 0;
}
}
void fill_sack() {
int a[MAXWEIGHT];
int last_added[MAXWEIGHT];
int i, j;
int aux;
for (i = 0; i <= W; ++i) {
a[i] = 0;
last_added[i] = -1;
}
a[0] = 0;
for (i = 1; i <= W; ++i)
for (j = 0; j < items; ++j)
if ((c[j] <= i) && (a[i] < a[i - c[j]] + v[j]) && taken[j] == 0) {
a[i] = a[i - c[j]] + v[j];
last_added[i] = j;
taken[j] = 1;
}
for (i = 0; i <= W; ++i)
if (last_added[i] != -1)
printf("Weight %d; Benefit: %d; To reach this weight I added object %d (%d$ %dKg) to weight %d.\n",
i, a[i], last_added[i] + 1, v[last_added[i]],
c[last_added[i]], i - c[last_added[i]]);
else
printf("Weight %d; Benefit: 0; Can't reach this exact weight.\n", i);
printf("---\n");
aux = W;
while ((aux > 0) && (last_added[aux] != -1)) {
printf("Added object %d (%d$ %dKg). Space left: %d\n",
last_added[aux] + 1, v[last_added[aux]],
c[last_added[aux]], aux - c[last_added[aux]]);
aux -= c[last_added[aux]];
}
printf("Total value added: %d$\n", a[W]);
}
int main(int argc, char *argv[]) {
takenOrNot();
fill_sack();
return 0;
}
Could you guys help me please? :)
This might help...!
public class Knapsack
{
int knapsackSize;
int[] _weights;
int[] _values;
int[,] results;
public Knapsack(int[] weights, int[] values, int size)
{
_weights = weights;
_values = values;
knapsackSize = size;
}
public int CreateSolution()
{
results = new int[_weights.Length + 1, knapsackSize + 1];
for (int i = 0; i < _weights.Length; i++) // item 1 to n
{
for (int j = 1; j <= knapsackSize; j++) //weight 1 to m
{
if (_weights[i] > j)
{
//if item weight is grater than knapsack capacity
results[i + 1, j] = results[i, j];
}
else
{
if (results[i, j] > (_values[i] + results[i, j - _weights[i]]))
{
//if previously calculated value only is grater
results[i + 1, j] = results[i, j];
}
else
{
//if including current item gives more value
results[i + 1, j] = _values[i] + results[i, j - _weights[i]];
}
}
}
}
return results[_weights.Length, knapsackSize]; // index (n, m) will be max value
}
static void Main(string[] args)
{
Knapsack demo = new Knapsack(new int[] { 23, 26, 20, 18, 32, 27, 29, 26, 30, 27 }, new int[] { 505, 352, 458, 220, 354, 414, 498, 545, 473, 543 }, 67);
Console.WriteLine("Solution is: " + demo.CreateSolution());
Console.ReadLine();
}
}