c++ - Algorithm to make numbers from match sticks -


i made program solve this problem acm.

matchsticks ideal tools represent numbers. common way represent ten decimal digits matchsticks following:

this identical how numbers displayed on ordinary alarm clock. given number of matchsticks can generate wide range of numbers. wondering smallest , largest numbers can created using matchsticks.

input

on first line 1 positive number: number of testcases, @ 100. after per testcase:

one line integer n (2 ≤ n ≤ 100): number of matchsticks have. output

per testcase:

one line smallest , largest numbers can create, separated single space. both numbers should positive , contain no leading zeroes. sample input

4 3 6 7 15 sample output

7 7 6 111 8 711 108 7111111

the problem it's way slow solve 100 matchsticks. search tree big bruteforce it.

here results first 10:

2: 1 1

3: 7 7

4: 4 11

5: 2 71

6: 6 111

7: 8 711

8: 10 1111

9: 18 7111

10: 22 11111

the pattern maximums easy don't see shortcut minimums. can suggest better way solve problem? here code used:

    #include <iostream>     #include <string>     using namespace std;      #define max 20 //should 100      //match[i] contains number of matches needed form     int match[] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6};     string mi[max+1], ma[max+1];     char curr[max+1] = "";      //compare numbers saved strings     int mycmp(string s1, string s2)     {         int n = (int)s1.length();         int m = (int)s2.length();         if (n != m)             return n - m;         else             return s1.compare(s2);     }      //i current digit, used number of matchsticks far     void fill(int i, int used)     {         //check smaller , bigger values         if (mycmp(curr, mi[used]) < 0) mi[used] = curr;         if (mycmp(curr, ma[used]) > 0) ma[used] = curr;          //recurse further, don't start numbers 0         (int = ? '0' : '1'; <= '9'; a++) {             int next = used + match[a-'0'];             if (next <= max) {                 curr[i] = a;                 curr[i+1] = '\0';                 fill(i + 1, next);             }         }     }      int main()     {         //initialise          (int = 0; <= max; i++) {             mi[i] = string(max, '9');             ma[i] = "0";         }          //precalculate values         fill(0, 0);          int n;         cin >> n;          //print asked         while (n--) {             int num;             cin >> num;             cout << mi[num] << " " << ma[num] << endl;         }          return 0;     } 

edit : ended using dynamic programming solution. tried dp before messing around two-dimensional state array. solutions here better. thanks!

in order find result :

  • first find minimal number of digits smallest number
  • then proceed significant digit least significant one.

every digit should chosen there exists solution remaining digits. each digit requires between 2 , 7 matches. must choose smallest nth "top" digit leaves number of remaining matches between 2*(n-1) , 7*(n-1).

do not forget 0 has excluded search significant digit of result.

as sidenote, 1 reason makes algorithm work fact there @ least 1 corresponding digit every value (of matches) between 2 , 7.

edit : example 10 matches 10 matches --> 2 digits
acceptable number of matches top digit = between 3 , 7.
smallest digit requires between 3 , 7 matches -> 2 (which takes 5 matches), 0 being excluded.
chosen first digit = 2

5 remaining matches -->
acceptable number of matches second (and in case last) digit = 5
smallest digit requires 5 matches -> 2
chosen second digit = 2

result = 22.

edit code problem

#include <iostream> #include <vector>  std::vector<int> nbmatchesfordigit;  long long minnumberformatches(unsigned int nbmatches) {     int nbmaxmatchesforonedigit = 7;     int nbminmatchesforonedigit = 2;     int remainingmatches = nbmatches;     int nbdigits = 1 + nbmatches / nbmaxmatchesforonedigit;      long long result = 0;     (int iddigit = 0 ; iddigit < nbdigits ; ++iddigit )     {         int minmatchestouse = std::max(nbminmatchesforonedigit, remainingmatches - nbmaxmatchesforonedigit * (nbdigits - 1 - iddigit));         int maxmatchestouse = std::min(nbmaxmatchesforonedigit, remainingmatches - nbminmatchesforonedigit * (nbdigits - 1 - iddigit));         (int digit = iddigit > 0 ? 0 : 1 ; digit <= 9 ; ++digit )         {             if( nbmatchesfordigit[digit] >= minmatchestouse &&                  nbmatchesfordigit[digit] <= maxmatchestouse )             {                 result = result * 10 + digit;                 remainingmatches -= nbmatchesfordigit[digit];                 break;             }         }     }     return result; }  int main() {     nbmatchesfordigit.push_back(6);     nbmatchesfordigit.push_back(2);     nbmatchesfordigit.push_back(5);     nbmatchesfordigit.push_back(5);     nbmatchesfordigit.push_back(4);     nbmatchesfordigit.push_back(5);     nbmatchesfordigit.push_back(6);     nbmatchesfordigit.push_back(3);     nbmatchesfordigit.push_back(7);     nbmatchesfordigit.push_back(6);      for( int = 2 ; <= 100 ; ++i )     {         std::cout << << " " << minnumberformatches(i) << std::endl;     } } 

Comments

Popular posts from this blog

linux - Using a Cron Job to check if my mod_wsgi / apache server is running and restart -

actionscript 3 - TweenLite does not work with object -

jQuery Ajax Render Fragments OR Whole Page -