Example of Knapsack algorithm.

NOTIFICATION: These examples are provided for educational purposes. Using this code is under your own responsibility and risk. The code is given ‘as is’. I do not take responsibilities of how they are used.

knapsack.c:

/**
 * Knapsack Algorithm
 * @author: Alejandro G. Carlstein R. M.
 * @description: Simple Knapsack algorithm
 */
#include <stdio.h>

/* Macros Functions */
#define max(a,b) \
           ({ typeof (a) _a = (a); \
              typeof (b) _b = (b); \
            _a > _b ? _a : _b; })

/* Debugging flags */
#define DBG_LV1 0
#define DBG_LV2 0

/* Constants */
#define MAX_STRING_LEN 80
#define MAX_ITEMS 100
#define MAX_WEIGHT 1000

/* This is an item we can put into the knapsack. */
typedef struct{
  char name[MAX_STRING_LEN];
  int weight;
  int value;
} item;

/* Our dynamic programming table element.  We have the value
 * that we can store, and also a way to remember what we selected.
 */
typedef struct{
  int value;
  int prev_row;
  int prev_column;
} prog;

void print_table(int num_items, int max_weight);
void print_table_prev_xy(int num_items, int max_weight);

/* The actual DP table, and the items.  Note that we have an extra
 * row and column in the table for the 'zero elements' and 'no weight'
 * situation.
 */
prog table[MAX_ITEMS + 1][MAX_WEIGHT + 1];

item items[MAX_ITEMS];

int main(int argc, char *argv[]){

  int num_items; // Number of items
  int w; // Weight
  int max_weight;
  int n; // Item number;
  int i, j;
  int diff_weight;

  /* Read in the maximum weight and number of items. */
  scanf('%d %d', &max_weight, &num_items);

  if (DBG_LV2){
    printf('\nMax Weight: %d, Number of Items: %d \n\n', max_weight, num_items);
    printf('READ ITEMS\nw v name\n');
  }//end if

  /* Read in the items */
  for (n = 0; n < num_items; ++n){
      scanf('%d %d %s',
            &items[n].weight,
            &items[n].value,
            items[n].name);

     if (DBG_LV1)
        printf('%d %d %s\n',
               items[n].weight,
               items[n].value,
               items[n].name);
  }//end for

  if(DBG_LV2)
    printf('\n');

  /* Initialize the first row of the table. */
  for (w = 0; w <= max_weight; ++w){
      table[0][w].value = 0;
      table[0][w].prev_row = table[0][w].prev_column = -1;
  }//end for

  // Fill in the table
  // Your code goes here.
  // Should be a for loop for the items, a for loop for the weight,
  // and inside all of that, a few if statements to determine if you
  // can take an item -- and if so, do you want to?
  //
  // I strongly recommend printing out EVERY DECISION your program
  // makes while debugging things -- and feed your program very small
  // problems until it's running.
  //
  // Debugging code is an important skill.  If you can work through a
  // problem by hand, you should be able to get your code to solve the
  // same thing.

  /* Initialize the first column of the table */
  for (i= 0; i <= num_items; ++i){
    table[i][0].value = 0;
  }

  if (DBG_LV2){
    printf('TABLE VALUES\n');
    print_table(num_items, max_weight);
  }//end if

  if (DBG_LV2){
    printf('TABLE PREVIOUS COORDINATES\n');
    print_table_prev_xy(num_items, max_weight);
  }//end if

  // Perform knapsack and find maximun value
  for (i = 1; i <= num_items; ++i){

    for (w = 0; w <= max_weight; ++w){

  		table[i][w].prev_row = i - 1;
		  table[i][w].prev_column = w;			

			// Check if item fit inside the knapsack

			if(items[i - 1].weight <= w) {

        int diff_weight = w - items[i - 1].weight;

        // Check which value is higher
				table[i][w].value = max((items[i - 1].value +
                    				    table[i - 1][diff_weight].value),
                    				    table[i - 1][w].value);

        // Keep track of the previous column
				if(table[i][w].value > table[i - 1][w].value)

					table[i][w].prev_column = diff_weight;

			}else{

				table[i][w].value = table[i - 1][w].value;

			}//end if

    }//end for

  }//end for

  if (DBG_LV2){
    printf('************\n\n');
  }//end if

  if (DBG_LV2){
    printf('TABLE VALUES\n');
    print_table(num_items, max_weight);
  }//end if

  if (DBG_LV2){
    printf('TABLE PREVIOUS COORDINATES\n');
    print_table_prev_xy(num_items, max_weight);
  }//end if

  // In my code, the maximum value is here.
  // I can use the prev_row and prev_column to trace back the solution.
  if (DBG_LV1)
    printf('Maximum value is %d\n', table[num_items][max_weight].value);

  if (DBG_LV2){
    printf('************\n\n');
  }//end if

  // Print results:

  w = max_weight;

  int count = -1;

	int t;

	int total_weight = 0;

  item *p_items[MAX_ITEMS];

	for(i = num_items;
	    i > 0;
	    t = w,
	    w = table[i][w].prev_column,
	    i = table[i][t].prev_row){

		if(table[i][w].value != table[i - 1][w].value){

			total_weight += items[i - 1].weight;

			p_items[++count] = &items[i - 1];

	  }//end if

	}//end for

	printf('%d\n', table[num_items][max_weight].value);

	printf('%d\n', total_weight);

  for (i = 0; i <= count; ++i){

    printf('%d %d %s \n',
           p_items[i]->weight,
           p_items[i]->value,
           p_items[i]->name);

  }//end for

}

/*
 *
 */
void print_table(int num_items, int max_weight){

  int w,i;

   for (i = 0; i <= num_items; ++i){
     for (w = 0; w <= max_weight; ++w){
       printf('%d ', table[i][w].value);
    }//end for
    printf('\n');
   }//end for
   printf('\n');

}

/*
 *
 */
void print_table_prev_xy(int num_items, int max_weight){

  int w,i;

   for (i = 0; i <= num_items; ++i){
     for (w = 0; w <= max_weight; ++w){
       printf('[%d,%d] ', table[i][w].prev_row, table[i][w].prev_column);
    }//end for
    printf('\n');
   }//end for
   printf('\n');

}

input.txt:

5
4
2 3 item_A
3 4 item_B
4 5 item_C
5 6 item_D

If you encounter any problems or errors, please let me know by providing an example of the code, input, output, and an explanation. Thanks.

© 2010, Alejandro G. Carlstein Ramos Mejia. All rights reserved.

Share

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.

*

Click to Insert Smiley

SmileBig SmileGrinLaughFrownBig FrownCryNeutralWinkKissRazzChicCoolAngryReally AngryConfusedQuestionThinkingPainShockYesNoLOLSillyBeautyLashesCuteShyBlushKissedIn LoveDroolGiggleSnickerHeh!SmirkWiltWeepIDKStruggleSide FrownDazedHypnotizedSweatEek!Roll EyesSarcasmDisdainSmugMoney MouthFoot in MouthShut MouthQuietShameBeat UpMeanEvil GrinGrit TeethShoutPissed OffReally PissedMad RazzDrunken RazzSickYawnSleepyDanceClapJumpHandshakeHigh FiveHug LeftHug RightKiss BlowKissingByeGo AwayCall MeOn the PhoneSecretMeetingWavingStopTime OutTalk to the HandLoserLyingDOH!Fingers CrossedWaitingSuspenseTremblePrayWorshipStarvingEatVictoryCurseAlienAngelClownCowboyCyclopsDevilDoctorFemale FighterMale FighterMohawkMusicNerdPartyPirateSkywalkerSnowmanSoldierVampireZombie KillerGhostSkeletonBunnyCatCat 2ChickChickenChicken 2CowCow 2DogDog 2DuckGoatHippoKoalaLionMonkeyMonkey 2MousePandaPigPig 2SheepSheep 2ReindeerSnailTigerTurtleBeerDrinkLiquorCoffeeCakePizzaWatermelonBowlPlateCanFemaleMaleHeartBroken HeartRoseDead RosePeaceYin YangUS FlagMoonStarSunCloudyRainThunderUmbrellaRainbowMusic NoteAirplaneCarIslandAnnouncebrbMailCellPhoneCameraFilmTVClockLampSearchCoinsComputerConsolePresentSoccerCloverPumpkinBombHammerKnifeHandcuffsPillPoopCigarette