2021.寒假集訓Day6
技術標籤:好好學習
今天上午陳老闆給我們講了資料結構:二叉樹、堆排序、雜湊表、字串字首雜湊法、拉鍊法、開放定址法等一些知識。稍微有點晦澀,不是太好理解。然後做題的時候發現果然不會做,不知道怎麼用所學的知識。今天先做了一道Flying to the Mars,我看了一下題目就想到用一維陣列記錄之後再用快排得出最大值,然後做了之後提交,果不其然TLE了。這個時候我就在想這道題應該要用今天上午說到的二叉樹或者雜湊表去做,但是我還是不死心的優化了我的程式碼,我把快排改成了一個for迴圈,遍歷一遍陣列記錄最大值直接輸出,然後又交,果不其然又TLE了,下午我優化程式碼優化了好久,交了七發TLE之後我終於妥協了。
先開一個N的字串陣列,用字串輸入士兵的等級。然後用字串字首雜湊法把30位的陣列變小,變小之後再用二叉堆求出最大值,或者用sort或者用for迴圈求也可以。
不確定這樣想是不是對的,也是一種思路,可能過幾天讓我們自己練的時候會嘗試一下。
然後我還看了一個關於這題的程式碼,手跑了一遍理解了解法:先用一個int的陣列把n個數存進去,然後sort排序,然後用兩個for迴圈遍歷這個陣列,第一個for迴圈設一個條件,如果不滿足就不進入第二個for迴圈,然後第二個for迴圈裡面也設條件,如果滿足就把這個數標記一下(讓陣列[j]=-1),相當於在一層迴圈的時候把這數劃掉,然後再重新進入第一層迴圈的時候每個數都被劃掉了一次,此時count++,然後繼續迴圈再一層層劃掉剩下的數。最後輸出這個count。
然後我用這個方法敲了一遍之後,倔強地沒使用sort,而是用了手打的快排,然後TLE了,我改成sort再交,AC了。整個人就是大寫的無語了(ˉ▽ˉ;)…
在我想A題的時候我還看了一下E題,然後敲了敲AC了,下面我把這兩題的題目和我今天寫過的程式碼附上來。
E - 雜湊表
現在給你n個箱子,再給你n個物品。每個物品都有它的價值ai。要求,你把這n個物品,放入這n個箱子中。安放規則:將第i個物品放入第ai%n的箱子中,如果這個箱子中有物品,就往下找沒有放物品的箱子,將它放入其中,如果你要把物品放最後一個箱子,但是最後一個箱子有物品,就從第一個箱子放下找沒放物品的箱子。
T組測試資料,每組第一行想輸入一個數n,代表n個箱子和n(0<n<=1000)個物品;下一行輸入n個物品的價值ai.
output:
先輸出一行“Case #num:”,num代表輸出的是第幾組資料。
下一行輸出這n個箱子中的物品的價值,最後一個箱子中的物品後換行。
Sample Input
3
5
0 1 2 3 4
5
1 2 3 4 9
5
1 6 2 3 4
Sample Output
Case #1:
0 1 2 3 4
Case #2:
9 1 2 3 4
Case #3:
4 1 6 2 3
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int box[1010];
int n;
void box_h(int x,int y){
for(int i=x;i<n;i++){
if(box[i]==0){
box[i]=y;
return;
}
}
for(int i=0;i<x;i++){
if(box[i]==0){
box[i]=y;
return;
}
}
}
int main(int argc,char const*argv[]){
int T,x,y;
int a[1010];
cin>>T;
int M=1;
while(T--){
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
x=a[i]%n;
y=a[i];
box_h(x,y);
}
cout<<"Case #"<<M<<":"<<endl;
for(int i=0;i<n;i++){
cout<<box[i];
if(i!=n-1){
cout<<" ";
}
}
cout<<endl;
M++;
memset(box,0,sizeof(box));
}
return 0;
}
這題比較簡單,題目都把解法告訴我們了,寫得比較快樂。
A - Flying to the Mars
In the year 8888, the Earth is ruled by the PPF Empire . As the population growing , PPF needs to find more land for the newborns . Finally , PPF decides to attack Kscinow who ruling the Mars . Here the problem comes! How can the soldiers reach the Mars ? PPF convokes his soldiers and asks for their suggestions . “Rush … ” one soldier answers. “Shut up ! Do I have to remind you that there isn’t any road to the Mars from here!” PPF replies. “Fly !” another answers. PPF smiles :“Clever guy ! Although we haven’t got wings , I can buy some magic broomsticks from HARRY POTTER to help you .” Now , it’s time to learn to fly on a broomstick ! we assume that one soldier has one level number indicating his degree. The soldier who has a higher level could teach the lower , that is to say the former’s level > the latter’s . But the lower can’t teach the higher. One soldier can have only one teacher at most , certainly , having no teacher is also legal. Similarly one soldier can have only one student at most while having no student is also possible. Teacher can teach his student on the same broomstick .Certainly , all the soldier must have practiced on the broomstick before they fly to the Mars! Magic broomstick is expensive !So , can you help PPF to calculate the minimum number of the broomstick needed .
For example :
There are 5 soldiers (A B C D E)with level numbers : 2 4 5 6 4;
One method :
C could teach B; B could teach A; So , A B C are eligible to study on the same broomstick.
D could teach E;So D E are eligible to study on the same broomstick;
Using this method , we need 2 broomsticks.
Another method:
D could teach A; So A D are eligible to study on the same broomstick.
C could teach B; So B C are eligible to study on the same broomstick.
E with no teacher or student are eligible to study on one broomstick.
Using the method ,we need 3 broomsticks.
……
After checking up all possible method, we found that 2 is the minimum number of broomsticks needed.
Input
Input file contains multiple test cases.
In a test case,the first line contains a single positive number N indicating the number of soldiers.(0<=N<=3000)
Next N lines :There is only one nonnegative integer on each line , indicating the level number for each soldier.( less than 30 digits);
Output
For each case, output the minimum number of broomsticks on a single line.
Sample Input
4
10
20
30
04
5
2
3
4
3
4
Sample Output
1
2
這題就是讓我們輸出輸入的數字中重複最多的數字的個數。
下面這個解法超時了,
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int q[31];
//快排
void quick_sort(int a[],int l,int r){
if(l<r){
int i=l,j=r,x=q[i];
while(i<j){
while(i<j&&q[j]<x){j--;}
if(i<j){
q[i]=q[j];
i++;
}
while(i<j&&q[i]>x){i++;}
if(i<j){
q[j]=q[i];
j--;
}
}
q[i]=x;
quick_sort(q,l,i-1);
quick_sort(q,i+1,r);
}
}
int main(int argc,char const*argv[]){
int n,x;
while(cin>>n){
/輸入的時候在陣列中記錄
for(int i=0;i<n;i++){
cin>>x;
q[x]++;
}
quick_sort(q,0,30); //進行排序
cout<<q[0]<<endl; //輸出
memset(q,0,sizeof(q)); 清空陣列為下一次輸入資料做準備
}
return 0;
}
然後我優化了一下,
while(cin>>n){
//用y記錄輸入的數中最大的數
for(int i=0;i<n;i++){
cin>>x;
if(x>y){
y=x;
}
q[x]++;
}
//找出記錄次數的陣列中最多的次數
for(int i=0;i<x+1;i++){
if(q[i]>k){
k=q[i];
}
}
cout<<k<<endl; //輸出
memset(q,0,sizeof(q)); //清空陣列為下一次輸入資料做準備
還是超時了/(ㄒoㄒ)/
下面是AC解法:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<queue>
using namespace std;
int main(int argc,char const*argv[]){
int n;
int sb[3005];
int point;
while(~scanf("%d",&n)){
for(int i=0;i<n;i++){
scanf("%d",&sb[i]);
}
//用手打快排超時了
sort(sb,sb+n);
int count=0;
for(int i=0;i<n;i++){
//這個數沒被標記過則進入條件
if(sb[i]!=-1){
count++;
point=sb[i]; //給每輪j的迴圈的第一個point賦值
//進入迴圈,遍歷陣列,每輪標記一次數
for(int j=i+1;j<n;j++){
//如果沒被標記,且小於前一個數,則進行標記,讓point一直保持這層迴圈中的最大值,前面排序就是為了這步
if(sb[j]!=-1&&sb[j]>point){
point=sb[j];
sb[j]=-1;
}
}
}
// cout<<sb[i]<<endl;
}
cout<<count<<endl; //輸出答案
}
return 0;
}
我剛剛試了試把scanf換成cin,結果TLE了。