CodeChef
  • PRACTICE
    • Easy
    • Medium
    • Hard
    • Challenge
    • Peer
  • COMPETE
  • DISCUSS
    • Wiki
    • Forums
    • Blog
    • Twitter
  • COMMUNITY
    • CodeChef Meetups
    • Campus Chapters
    • Host Your Contest
    • User Groups
    • CodeChef TechTalks
  • HELP
    • Frequently Asked Questions
    • FAQ for Problem Setters
    • Ranks
    • Tutorials
  • ABOUT
    • About CodeChef
    • Team CodeChef
    • Press Room
    • CEO's Corner
    • About Directi

Tutorial for problem “Paying Up”

Posted by Aniruddha on July 9th, 2009 Filed in Tutorials View Comments

Hello,

The problem “Paying Up” was one of the easy ones in the March 2009 contest on Codechef. It is considered an easy problem, because it has a couple of approaches that work. The problem statement boils down to finding a subset of banknotes such that their sum is exactly equal to a certain value. Now, this problem is somewhat similar to the knapsack problem which asks for ways to fill up a knapsack of a certain size optimally with the given blocks. There is a solution based on dynamic programming for this problem, but we will be taking up a solution which makes good use of the way integers are represented in binary to solve this problem.

Now, the limit on the number of banknotes is ‘n’. Let us see how many subsets exist for these banknotes. For finding the number of subsets, we see that for every banknote, we have two choices, either to choose it in our calculation for the sum of notes or to ignore it in calculating the sum. Thus, we have 2 options per banknote and ‘n’ banknotes. So, the total number of subsets thus becomes 2^n where ^ represents the power operation. The number of subsets are small enough for us to bruteforce through them and the program to run in time.

An interesting way to generate all subsets of ‘n’ objects when ‘n’ is considerably small (n <= 20) is to use the properties of how unsigned integers are stored. Consider the number 2^n. This number is represented in binary form as ’10000…0′, that is, 1 followed by n 0s. Also, any number containing a 1 at the same position will surely be greater than 2^n. Thus, all numbers below 2^n do not have a 1 in a position greater than or equal to ‘n’ starting from the LSB. By induction, we can do the same for values of n = n-1 and n-2 and so on. Thus, we can see that any number between 2^(n-1) and 2^n will have a 1 in the position n-1. Extending this logic, we can say that if we consider the numbers from 1 to 2^n, we would be considering all possible ways in which we can choose some objects from ‘n’ objects.

For example, consider n = 3, so 2^n = 8. Let us list ‘i’ and its binary representation
i    Binary representation using ‘n’ bits
0    000
1    001
2    010
3    011
4    100
5    101
6    110
7    111

As you can see, if we consider that 1 means that we have selected object at that position and 0 means that we have not selected the object at that position, we can get all possible subsets of ‘n’ objects by looping over numbers from 1 to 2^n.

For calculating the sum of the subset represented by ‘i’, we loop from 0 to ‘n’ and we check whether the corresponding bit is set in the value for ‘i’ or not. If it is, we include that object in calculating our sum else we don’t. In this way, we can get the sum for all possible subsets of the ‘n’ objects.

This is exactly what we need for this problem. After taking in the number of objects, we loop ‘i’ from 1 to 2^n incrementing the value of ‘i’ by 1 at every stage to give us a new subset. Then for a particular value of ‘i’, we loop ‘j’ from 0 to n and check if the bit at that particular value is set or not. Languages like C / C++ provide bit-wise operators for leftshift and rightshift. For checking if the bit is set at position ‘j’(starting from 0) we can just check if the value of (i & (1<<j)) is 0. If it is 0, then the bit is not set, while if it is greater than 0, then the bit is set. Alternatively, we can also loop from 0 to n and at each stage check whether ‘i’ modulo 2 is equal to 1 or not. If it is 1, then the bit at that position is set, else it’s not. Then we divide ‘i’ by 2 and proceed. At the end of the ‘n’ iterations, ‘i’ will equal 0. The problem with this appraoch is that the modulo operations take much more time compared to the bitwise operations. Thus, now that we know how to check if the bit is set, we initialize a value ‘sum’ equal to 0 at the start of the ‘n’ iterations for a value of ‘i’ and if the bit at position ‘j’ is set, we add the corresponding banknote value to ‘sum’ else we don’t. At the end of these iterations, we check if the value of ‘sum’ equals the required value. If it does, then we have found a subset with the required sum and so we print a “Yes” and exit. Else, if at the end of 2^n iterations of ‘i’ we don’t have a subset with the required sum, then we print a “No” and exit.

The program should look something like this :

Start
Take in the value of 'n' and the required value of sum 'm'
Take in all the values for the banknotes in array 'd[]'
For i = 1 and i < (2^n)
    sum = 0
    For j = 0 and j < n
        if jth bit of i is set
            sum = sum + d[j]
    if sum equals m
        print Yes and return
Print No and return

  • Share/Bookmark
  • http://devwebcl.blogspot.com/ German

    Good tutorials always are welcome, but the code template doesn’t appear clear on Firefox 3.5 (it happened the same with the before tutorial.

    It’s easy what I may do to see it right, however I think it’s a usability problem that should be fixed easily (w/CSS).

    Kind Regards

    German

  • http://devwebcl.blogspot.com/ German

    Good tutorials always are welcome, but the code template doesn’t appear clear on Firefox 3.5 (it happened the same with the before tutorial.

    It’s easy what I may do to see it right, however I think it’s a usability problem that should be fixed easily (w/CSS).

    Kind Regards

    German

  • pushkar

    code appears properly on safari

  • pushkar

    code appears properly on safari

  • http://www.codechef.com The Chef

    This is fixed. Thanks for pointing it out.

  • http://www.codechef.com The Chef

    This is fixed. Thanks for pointing it out.

  • RM

    thanks 4 d tutorial…itz helpin newbies like me 2 get 2 kno better ways….pls keep on postim more!!!

  • RM

    thanks 4 d tutorial…itz helpin newbies like me 2 get 2 kno better ways….pls keep on postim more!!!

  • Ankush

    Gr8 one sir! ! !

  • Ankush

    Gr8 one sir! ! !

  • nishant

    Thanks a lot for tutorials.Its like a guide to newbies for getting accustomed to the problems…
    keep posting them.
    regards..

  • nishant

    Thanks a lot for tutorials.Its like a guide to newbies for getting accustomed to the problems…
    keep posting them.
    regards..

  • shivam gupta

    I have another solution for this problem……
    We can find all possible additions and store it in another array and compare the sum with each element

    Let me give u an example…..
    lets have 3 banknotes as 2,4,7 so possible combinations are 2,4,6,7,9,11,13 which we will store in another array

    here is the algo for it

    1.Start

    2.Accept the value of n and m

    3.Accept all values of banknotes in an array a[]

    4.declare an array b[] having first element initialised as 0 i.e. b[0]=0

    5.set flag=0 and top=0
    //here top is used as continuous insertion of
    //elements in b[] and flag is used to add all
    //elements in b[] with a new banknote and store
    //it further in b[]

    6.for i=0 till i<n incremented each time by 1

    7. for j=0 till j<=flag incremented each time by 1

    8. top=top+1 , b[top]=a[i]+b[j]

    9. flag=top

    10.Now compare each element of b[] with m and print
    yes if search is successful otherwise no

    11.End

    The above algo can be modified depending upon the problem…….

  • shivam gupta

    I have another solution for this problem……
    We can find all possible additions and store it in another array and compare the sum with each element

    Let me give u an example…..
    lets have 3 banknotes as 2,4,7 so possible combinations are 2,4,6,7,9,11,13 which we will store in another array

    here is the algo for it

    1.Start

    2.Accept the value of n and m

    3.Accept all values of banknotes in an array a[]

    4.declare an array b[] having first element initialised as 0 i.e. b[0]=0

    5.set flag=0 and top=0
    //here top is used as continuous insertion of
    //elements in b[] and flag is used to add all
    //elements in b[] with a new banknote and store
    //it further in b[]

    6.for i=0 till i<n incremented each time by 1

    7. for j=0 till j<=flag incremented each time by 1

    8. top=top+1 , b[top]=a[i]+b[j]

    9. flag=top

    10.Now compare each element of b[] with m and print
    yes if search is successful otherwise no

    11.End

    The above algo can be modified depending upon the problem…….

  • shivam gupta

    i forgot to add that step 8 is inside inner for and step 9 is inside outer for i.e.
    step 6
    {
    step 7
    {
    step 8
    }
    step 9
    }

  • shivam gupta

    i forgot to add that step 8 is inside inner for and step 9 is inside outer for i.e.
    step 6
    {
    step 7
    {
    step 8
    }
    step 9
    }

  • Aniruddha

    Please don’t post code in the comments section on the blog. Post your doubts on the problem page and not here.

blog comments powered by Disqus

Recent Posts

  • A new boost for CodeChef Long Contest!
  • The February Long Challenge has a Surprise in store!
  • Gennady’s blitz·krieg!
  • An overwhelming participation for IOPC2012 :)
  • IIT-Kanpur along with CodeChef presents Techkriti-IOPC 2012

Categories

  • About (15)
  • Announcement (91)
  • Campus Chapters (4)
  • Contests (95)
  • Events (17)
  • Features (19)
  • Meetup (4)
  • Open Source (1)
  • Practice Problems (6)
  • Prizes (32)
  • Programmer of the Month (27)
  • Tech Talks (2)
  • Tutorials (24)
  • Winners (44)

Recent Comments

  • Gennady on A new boost for CodeChef Long Contest!
  • Anonymous on A new boost for CodeChef Long Contest!
  • hacker007 on A new boost for CodeChef Long Contest!
  • Tejwinder91 on The February Long Challenge has a Surprise in store!
  • sourcecode on The February Long Challenge has a Surprise in store!

Recent Pictures

Blogroll

  • Documentation
  • Plugins
  • Suggest Ideas
  • Support Forum
  • Themes
  • WordPress Blog
  • WordPress Planet

Archives

  • February 2012
  • January 2012
  • December 2011
  • November 2011
  • October 2011
  • September 2011
  • August 2011
  • July 2011
  • June 2011
  • May 2011
  • April 2011
  • March 2011
  • February 2011
  • January 2011
  • December 2010
  • November 2010
  • October 2010
  • September 2010
  • August 2010
  • July 2010
  • June 2010
  • May 2010
  • April 2010
  • March 2010
  • February 2010
  • January 2010
  • December 2009
  • November 2009
  • October 2009
  • September 2009
  • August 2009
  • July 2009
  • June 2009
  • May 2009
  • April 2009
  • March 2009
  • February 2009
  • January 2009

Company Blogs

  • Directi
  • .pw Corp Blog
  • CEOs Blog

Careers@Directi


  • About CodeChef
  • About Directi
  • CEO's Corner
  • CodeChef Campus Chapters
  • Blogger Community Program
  • User Group Outreach Program

© 2009, Directi Group. All Rights Reserved.

Sponsors