TopCoder SRM285 -- My Solution

这次比赛是北京时间夜里12点开始的,所以没有参加。下面的代码是比赛后一天写的,都通过了系统测试:

Problems :

BasketsWithApples:

We have some baskets containing apples, and we would like to perform the following procedure in a way that maximizes the number of remaining apples. First, we discard some (or none) of the baskets completely. Then, if the remaining baskets do not all contain the same number of apples, we remove excess apples from the baskets until they do.

You will be given a vector <int> apples where the i-th element of apples is the number of apples in the i-th basket. Return the number of apples remaining after the procedure described above is performed.

Definition

    
Class: BasketsWithApples
Method: removeExcess
Parameters: vector <int>
Returns: int
Method signature: int removeExcess(vector <int> apples)
(be sure your method is public)

Constraints

- apples will contain between 1 and 50 elements, inclusive.
- Each element in apples will be between 0 and 1000, inclusive.

这一问题时Div2 Level 1 ,所以很简单,只需要对apples排序,然后假设最少的篮子中的水果数依次为apple[0],apple[1]...,计算出每种情况下的剩余水果数,选出其中最大的返回。

Code :

int BasketsWithApples::removeExcess(vector <int> apples)
{
 int size = apples.size();
 vector<int> Apples = apples;
 std::sort(Apples.begin(),Apples.end());
 int ret = Apples[0]*size;
 int left;
 int i;
 for(i=1;i<size;i++){
  left = Apples[i]*(size-i);
  if(left>ret) ret = left;
 }
 return ret;
}

SentenceSplitting

You have a sentence written entirely in a single row. You would like to split it into several rows by replacing some of the spaces with "new row" indicators. Your goal is to minimize the width of the longest row in the resulting text ("new row" indicators do not count towards the width of a row). You may replace at most K spaces.

You will be given a string sentence and an int K. Split the sentence using the procedure described above and return the width of the longest row.

Definition

    
Class: SentenceSplitting
Method: split
Parameters: string, int
Returns: int
Method signature: int split(string sentence, int K)
(be sure your method is public)

Constraints

- sentence will contain between 1 and 50 characters, inclusive.
- sentence will consist of only letters ('a'-'z', 'A'-'Z') and spaces (' ').
- Each space character in sentence will be between two letters.
- K will be between 1 and 50, inclusive.

这个问题第一次看的时候感觉很简单,用递归就可以了。但是在时间复杂度上却总是不能通过,经过反复优化,终于通过系统测试了。我的算法如下:

  1. if K == 0 then return sentence.size()
  2. 以' '为分隔符将sentence分割成string[],以vector<int> size 记录每一段的长度,vector<int>pos记录空格的位置
  3. if size.length()<= K then return max(size)
  4. if all element in size are same then calculate result directly
  5. 用length记录每种分法的结果,result记录最终结果
  6. for i = 1 to pos.size()
  7.        strone = sentence.substr(0,pos[i]);
  8.        strtwo = sentence.substr(pos[i]+1,end)
  9.        if strone.length >= strtwo.length then length = strone.length
  10.        else length = MAX(strone.length,split(sentence,K-1)
  11.        result = MIN(result,length)
  12. End loop
  13. return result

Code:

int SentenceSplitting::split(string sentence, int K)
{
 if(K==0) return sentence.size();
 string one,two;
 int i,j;
 int ret = 100;
 int length;
 bool find_space = false;
 vector<int> pos;
 pos.push_back(-1);
 vector<int> size;
 int size_min = 100;
 int size_max = 0;
 for(i=0;i<sentence.size();i++){
  if(sentence[i]==' '){
   //cout<<i<<endl;
   find_space = true;
   size.push_back(i-pos.back()-1);
   if(size_min>size.back()) size_min = size.back();
   if(size_max<size.back()) size_max = size.back();
   pos.push_back(i);
  }
 }
 size.push_back(sentence.size()-pos.back()-1);
 if(size_min>size.back()) size_min = size.back();
 if(size_max<size.back()) size_max = size.back();
 if(!find_space) return sentence.size();

 if(K>=(size.size()-1)){
  return *(std::max_element(size.begin(),size.end()));
 }
 if(size_min == size_max && K>3){
  int half = (int)(sentence.size()/2)+1;
  cout<<half<<endl;
  if(half%(K+1)==0){
   length = (int)(half/(K+1));
   return length*2-1;
  }else{
   length = (int)(half/(K+1))+1;
   return length*2-1;
  }
 }

 for(i=1;i<pos.size()-K+1;i++){
  one = sentence.substr(0,pos[i]);
  two = sentence.substr(pos[i]+1,sentence.size()-pos[i]);
  if(one.size()>=two.size()){
   length = one.size();
   ret = MIN(ret,length);
   break;
  }else{
   length = split(two,K-1);
   length = MAX(one.size(),length);
   ret = MIN(ret,length);
  }
 }
 return ret;
}

OperationsArrangement

You are given a sequence of digits. You must insert either a '+' (addition) operator or a '*' (multiplication) operator between each pair of adjacent digits in such a way that minimizes the value of the resulting expression. The expression should be evaluated using the standard order of operations (multiplication has a higher precedence than addition).

You will be given a string sequence. Perform the procedure described above on the sequence and return the resulting expression. If there are several possible answers, return the one that comes first lexicographically. Note that '*' comes before '+' lexicographically.

Definition

    
Class: OperationsArrangement
Method: arrange
Parameters: string
Returns: string
Method signature: string arrange(string sequence)
(be sure your method is public)
    
 

Constraints

- sequence will contain between 2 and 50 characters, inclusive.
- Each character in sequence will be a digit ('0'-'9').

这道题目并不难,就是要把所有的可能性考虑全不太容易,注意以下情形:

  1. 1*num < 1 + num
  2. 2*2 = 2+2
  3. '*' <'+'
  4. 如果sequence含有0,则运算符都赋 '*'

注意以上4点,就可以编出正确的代码:

string OperationsArrangement::arrange(string sequence)
{
 char* buf = new char[100];
 memset(buf,0,100);
 int i;
 int k = 0;
 bool find1,find2;
 if(sequence.find("0")!=string::npos){
  for(i=0;i<sequence.size()-1;i++){
   buf[k] = sequence[i];
   buf[k+1] = '*';
   k+=2;
  }
  buf[k] = sequence[sequence.length()-1];
 }else{
  find2 = false;
  find1 = false;
  int num = sequence[0]-'0';
  for(i=0;i<sequence.size()-1;i++){
   cout<<num<<" ";
   if(find1 == false && sequence[i] == '1'){
    find2 = false;
    buf[k] = sequence[i];
    buf[k+1] = '*';
    num = num*(sequence[i+1]-'0');
    k+=2;
    continue;
   }
   if(sequence[i] != '1') find1 = true;
   if(sequence[i+1] == '1'){
    find2 = false;
    buf[k] = sequence[i];
    buf[k+1] = '*';
    k+=2;
   }
   else if(sequence[i+1] == '2'){
    if((num<=2) && find2 == false){
     find2 = true;
     buf[k] = sequence[i];
     buf[k+1] = '*';
     num = num*2;
     k+=2;
    }else{
     find2 = false;
     buf[k] = sequence[i];
     buf[k+1] = '+';
     find1 = true;
     num = sequence[i+1]-'0';
     k+=2;
    }
   }
   else{
    find2 = false;
    buf[k] = sequence[i];
    buf[k+1] = '+';
    find1 = true;
    num = sequence[i+1]-'0';
    k+=2;
   }
  }
  buf[k]=sequence[sequence.length()-1];
 }
 string ret = buf;
 return ret;
}

给出一些结果,可供参考

"12121212121212121212121212121212121212121212121212"

1*2*1*2*1+2*1*2*1+2*1*2*1+2*1*2*1+2*1*2*1+2*1*2*1+2*1*2*1+2*1*2*1+2*1*2*1+2*1*2*
1+2*1*2*1+2*1*2*1+2

"11111111112111111111211121111112"

1*1*1*1*1*1*1*1*1*1*2*1*1*1*1*1*1*1*1*1*2*1*1*1+2*1*1*1*1*1*1*2

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值