TopCoder SRM280 -- My Solution

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));
 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值