TopCoder SRM280 -- My Solution

来源:互联网 发布:淘宝卖家中心新的网页 编辑:程序博客网 时间:2024/05/17 00:03

TopCoder SRM 280

SRM 280 - Problem Set & Analysis by lovro can be see here.

The following is my solution, all programs are pass system test.

The Problems

UniqueDigits

    This problem only test all integers less then n, and get the number of those whoes all digits all distinct.

    we just need a function to judge if a number's all digits are distinct from each other.

    the following are my codes:

string UniqueDigits::toString(int num)
 {
     int a = num;
     int b;
     string ret;
     while(true)
     {
         b = a%10;
         a = (int)(a/10);
         ret.insert((string::size_type)0,1,char(b+'0'));
         if(a==0) break;
     }
     return ret;
 }
 
 int UniqueDigits::count(int n)
 {
     int i,j,k;
     int ret = 0;
     for(i=1;i<n;i++)
     {
         string str = toString(i);
         //cout<<str<<endl;
         bool match = true;
         for(j=0;j<str.size();j++)
         {
             for(k=j+1;k<str.size();k++)
             {
                 if(str[j]==str[k]){
                     match = false;
                     break;
                 }
             }
             if(match == false) break;
         }
         if(match) ret++;
     }
     return ret;
 }

CompletingBrackets

        To solve this problem , I use vector as stack to calculate two number, one is how many brackets should append left

    and the other is how many should append right. the following is my code:

string CompletingBrackets::complete(string text)
 {
     vector<int> S;
     int i;
     string ret;
     for(i=0;i<text.size();i++)
     {
         if(text[i]=='['){
             S.push_back(0);
         }else if(text[i]==']'){
             if(S.size() == 0){
                 S.push_back(1);
                 continue;
             }
             if(S.back()==0){
                 S.pop_back();
             }
             else S.push_back(1);
         }
     }
     int one = 0;
     int zero = 0;
     for(i=0;i<S.size();i++){
         if(S[i] == 0) zero++;
         if(S[i] == 1) one++;
     }
     cout<<one<<" "<<zero<<endl;
     string A,B;
     for(i=0;i<zero;i++){
         A.insert((string::size_type)0,1,']');
     }
     for(i=0;i<one;i++){
         B.insert((string::size_type)0,1,'[');
     }
     cout<<A<<" "<<B<<endl;
     ret = B + text + A;
     return ret;
 }

GroupingNumbers

    This is the most difficult problem in Div.2. Many people can write the solution, but some test case will make there algorithm exceed time limit.

    My algorithm include two function :

    first function: give number N, m. find m numbers a1,a2,...,am; a1+a2+...+am = N and a1 >= a2 >= a3 ... >= am

    second function : solve the GroupingNumbers problem. In my solution, I search all permutations, and this do not exceed time limit.

    Following is my codes:

    First Function :

vector<vector<int> >GroupingNumbers::all(int number, int n, int minnum)
 {
     vector<vector<int> > ret;
     vector<int> one;
     if(number<minnum) return ret;
     if(n==1){
         if(number>=minnum){
             one.push_back(number);
             ret.push_back(one);
             return ret;
         }else return ret;
     }
     else{
         int i,j;
         for(i=minnum;i<=number-n+1;i++){
             vector<vector<int> > ret1 = all(number-i,n-1,i);
             for(j=0;j<ret1.size();j++){
                 one = ret1[j];
                 one.push_back(i);
                 ret.push_back(one);
             }
             ret1.clear();
         }
     }
     return ret;
 }

Second Function:

double GroupingNumbers::minRange(vector<int> number, int n)
 {
     vector<vector<int> > All = all(number.size(),n,1);
     vector<int> a;
     int i,j,k,h;
     double minave, maxave;
     vector<int> temp;
     double ret = 9999999999.9999;
     for(i=0;i<number.size();i++) a.push_back(i);
     bool end;
     do{
         for(i=0;i<All.size();i++)
         {
             k = 0;
             minave = 9999999999.9999;
             maxave = 0;
             end = false;
             for(j=0;j<All[i].size();j++){
                 temp.clear();
                 for(h=0;h<All[i][j];h++){
                     temp.push_back(number[a[k]]);
                     k++;
                 }
                 double ave = average(temp);
                 if(ave>maxave) maxave = ave;
                 if(ave<minave) minave = ave;
             }
             if(maxave - minave < ret){
                 ret = maxave - minave;
                 if(ret==0) return 0;
                 cout<<maxave<<" "<<minave<<endl;
             }
         }
     }while(std::next_permutation(a.begin(),a.end()));
     return ret;
 }

GridCut

    To solve this problem , we have to notice two things:

        1. To minimum the GridCut length, we must use the edge of rect

        2. Shapes with different area may have same perimeter

    I consider three condition :

        1. one edge have length of 'width'

        2. one egde have length of 'height'

        3. one edge < width and one edge < height

    Algorithm :

        int cutLength(int width, int height, int n)

            if n > width*height/2 then

                n = width*height - n ;  // cut length of one part equals to cut length of the left part

            int ret = INT_MAX

            for(i=1;i<width;i++)

                if n%i == 0 then ret = MIN(ret,i+(int)(n/i))

                else

                    j = (int)(n/i)+1

                    if(j<height)   then

                        ret = MIN(ret,i+j)

             if one edge have length 'width' then calculate cutlength c1

             if one edge have length 'height' then calculate cutlength c2

             ret = MIN(ret,c1,c2)

             return ret;

    Code:

int GridCut::cutLength(int width, int height, int n)
 {
     int area = width*height;
     int N = n;
     if(2*N>area) N = area - N;
     int c = INT_MAX;
     int i,j;
     if(N==0) return 0;
     int cur;
     for(i=1;i<width;i++){
         if(N%i == 0) c = MIN(c,i+(int)(N/i));
         else{
             j = (int)(N/i)+1;
             c = MIN(c,i+j);
         }
     }
     int r2,q2,c2;
     r2 = N%width;
     q2 = (int)(N/width);
     if(q2<height-1){
         if(r2 == 0) c2 = width;
         else c2 = width + 1;
     }else{
         c2 = width + 1 - r2;
     }
     int r3,q3,c3;
     r3 = N%height;
     q3 = (int)(N/height);
     if(q3<width-1){
         if(r3 == 0) c3 = height;
         else c3 = height + 1;
     }else{
         c3 = height + 1 - r3;
     }
     return MIN(c,MIN(c2,c3));
 }

原创粉丝点击