寒假集训Day6

今天上午陈老板给我们讲了数据结构:二叉树、堆排序、哈希表、字符串前缀哈希法、拉链法、开放寻址法等一些知识。稍微有点晦涩,不是太好理解。然后做题的时候发现果然不会做,不知道怎么用所学的知识。今天先做了一道Flying to the Mars,我看了一下题目就想到用一维数组记录之后再用快排得出最大值,然后做了之后提交,果不其然TLE了。这个时候我就在想这道题应该要用今天上午说到的二叉树或者哈希表去做,但是我还是不死心的优化了我的代码,我把快排改成了一个for循环,遍历一遍数组记录最大值直接输出,然后又交,果不其然又TLE了,下午我优化代码优化了好久,交了七发TLE之后我终于妥协了。
然后我又看了一遍题目,我发现我忽略了digits,题目的意思可能是士兵的等级位数小于等于30,而不是等级小于等于30,那我可能数组就开小了,但是30位数的数组太大了也没办法开,我想了一个方法,不过还没写,主要是还不懂怎么实现字符串哈希法,今天看了两个博客还是感觉没学懂,下面说一下我的想法:
先开一个N的字符串数组,用字符串输入士兵的等级。然后用字符串前缀哈希法把30位的数组变小,变小之后再用二叉堆求出最大值,或者用sort或者用for循环求也可以。
不确定这样想是不是对的,也是一种思路,可能过几天让我们自己练的时候会尝试一下。
然后我还看了一个关于这题的代码,手跑了一遍理解了解法:先用一个int的数组把n个数存进去,然后sort排序,然后用两个for循环遍历这个数组,第一个for循环设一个条件,如果不满足就不进入第二个for循环,然后第二个for循环里面也设条件,如果满足就把这个数标记一下(让数组[j]=-1),相当于在一层循环的时候把这数划掉,然后再重新进入第一层循环的时候每个数都被划掉了一次,此时count++,然后继续循环再一层层划掉剩下的数。最后输出这个count。
这个解法我觉得时间复杂度还挺大的,结果AC了,比较震惊。
然后我用这个方法敲了一遍之后,倔强地没使用sort,而是用了手打的快排,然后TLE了,我改成sort再交,AC了。整个人就是大写的无语了(ˉ▽ˉ;)…
在我想A题的时候我还看了一下E题,然后敲了敲AC了,下面我把这两题的题目和我今天写过的代码附上来。
E - 哈希表
现在给你n个箱子,再给你n个物品。每个物品都有它的价值ai。要求,你把这n个物品,放入这n个箱子中。安放规则:将第i个物品放入第ai%n的箱子中,如果这个箱子中有物品,就往下找没有放物品的箱子,将它放入其中,如果你要把物品放最后一个箱子,但是最后一个箱子有物品,就从第一个箱子放下找没放物品的箱子。
input:
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了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值