SYSU SSE algorithm lab5——mandatory and optional problems(English Version) Merging fruits, line segment coverage, milking cows, equally dividing playing cards, and deleting numbers

A-Combine Fruit

Problem Description

 Complete Code

#include<iostream>
#include<queue>
using namespace std;
int main()
{
  int n;
  int x;
  int res=0;
  priority_queue<int,vector<int>,greater<int>> heap;
  // value_type,container_type,compare.
  // the compare defaults to less<value_type>
  cin>>n;
  while(n--){
    cin>>x;
    heap.push(x);
  }

  while(heap.size()>1){
    int top1=0,top2=0;

    top1=heap.top();
    heap.pop();
    top2=heap.top();
    heap.pop();

    res+=top1+top2;

    heap.push(top1+top2);
  }
  cout<<res<<endl;
}

Code Explanation

The train of thought is to combine the two lightest fruit groups after using a priority_queue to sort them until there is only one group left.

B-Segment Overlap

Problem Description

 Complete Code

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main(){
  // input
  int n,start,end;
  vector<pair<int,int> > contest;
  cin>>n;
  for(int i=0;i<n;i++){
    cin>>start>>end;
    contest.push_back(make_pair(end,start));// reverse to avoid a comp func for sort
  }
  sort(contest.begin(),contest.end());
  int count=1;
  int tmp=0;
  for(int i=1;i<n;i++)
  {
    if(contest[i].second>=contest[tmp].first){
      count++;
      tmp=i;
    }
  }
  cout<<count<<endl;
}

Code Explanation

An ingenious design is that reversing the pair order avoids a comp function for sort.

tmp represents the current contest. We need to finish this contest before the start time we choose next. The application of the greedy algorithm in this problem is to choose the contest with the earliest end time.

C-Milk the cow

Problem Description

 Complete Code

#include<iostream>
#include<algorithm>
#include<queue>
#define PII pair<int,int> // the end time of cow in this stall, index of stall
using namespace std;

struct cow{
  int start;
  int end;
  int index;
};
cow cows[10000];

bool comp(cow a,cow b){
  return a.start<b.start;
}

int res[50001];

int main(){
  int n;
  cin>>n;

  for(int i=0;i<n;i++)
  {
    cin>>cows[i].start>>cows[i].end;
    cows[i].index=i;
  }

  priority_queue<PII,vector<PII>,greater<PII> > heap;
  sort(cows,cows+n,comp);

  int stallCount = 0; // Maintain a separate stall counter

  for(int i=0;i<n;i++){
    cow tmp=cows[i];
    // if there is no stall or the earliest end time of cow >= that start time of this cow, add a new stall in order to put the cow in it
    if(heap.empty()||heap.top().first>=tmp.start){
      stallCount++; // Increase stall count
      PII stall;
      stall.first=tmp.end; // end time of this cow
      stall.second=stallCount; // Use stallCount as index
      res[cows[i].index]=stall.second;
      heap.push(stall);
    }
    // if there is a stall to contain this cow, this time is updated to the cow's end time.
    else{
      PII stall=heap.top();
      heap.pop();
      stall.first=tmp.end;
      res[cows[i].index]=stall.second;
      heap.push(stall);
    }
  }

  cout<<heap.size()<<endl; //heap size represents the count of stall
  for(int i=0;i<n;i++)
    cout<<res[i]<<endl; // No need to add 1 since we are already using 1-based indexing for stalls
}

Code Explanation

see comments for details.

D-Split cards equally

Problem Description

 Complete Code

#include<iostream>
using namespace std;
int main(){
  int n;
  while(cin>>n&&n){
    int avg=0,res=0;
    int num[110]={0};
    for(int i=0;i<n;i++){
      cin>>num[i];
      avg+=num[i];
    }
    avg/=n;
    for(int i=0;i<n;i++)
      num[i]-=avg;
    int i=0,j=n-1;
    while(num[i]==0&&i<n)
      i++;
    while(num[j]==0&&j>=0)
      j--;
    while(i<j){
      num[i+1]+=num[i];
      num[i]=0;
      res++;
      i++;
      while(num[i]==0&&i<j)
        i++;
    }
    cout<<res<<endl;
  }
}

Code Explanation

A very TRICKY problem. (I learned this word from WYL this morning)

There is no need to solve the exact way to transfer cards. We just need to know whether there is a transfer or not. So it is enough to know whether is zero or not. If the num[i] is negative, it means that it need the other side to give card to it. If positive, it will give cards to others. 

Give some examples to clarify the concept "transfer".

Suppose that:

1 0 3 100

they become -25 -26 -23 74 after num[i]-=avg

in the first Wiley cycle:0 -51 -23 74, res=1.

the leftest 0 means that it doesn't need be given cards after one time.

Another simpler example:

1 5 2 4

afer -=avg: -2 2 -1 1

1 cycle:  0 0 -1 1, res =1. one transfer solve to cards heap.

2 cycle: 0 0 0 0, res =2.

E- Delete Number

Problem Description

Complete Code

#include<iostream>
#include<string>
using namespace std;

int main() {
  string n;
  int s;
  cin >> n >> s;

  for(int j = 0; j < s; ++j) {
    int i = 0;
    while(i < n.length() - 1 && n[i] <= n[i + 1]) {
      i++;
    }
    n.erase(n.begin() + i);
  }

  while(n.size() > 1 && n[0] == '0') {
    n.erase(n.begin());
  }

  cout << n << endl;
}

Code Explanation

At each step, always choose the smallest remaining number to remove, that is, search in descending order from the most significant digit to the least significant digit. If the digits are in increasing order, then remove the last digit; otherwise, remove the first character of the decreasing interval.

Note that use n.erase(begin()+i) instead of n.erase(i);

The erase function need a iterator instead of a direct index.

Guess you like

Origin blog.csdn.net/weixin_64123373/article/details/133323762