机试-经典入门


##排序

c++ 快速排序库函数,头文件需包含 algorithm,并使用标准命名空间(sort 被定义在其中),我们也可以定义新的排序规则:

#include<stdio.h>
#include<algorithm>
using namespace std;
// sort 逆序

bool cmp(int x, int y){        //定义排序规则
    return x>y;
}

int main(){
    int n;
    int buf[100];

    while(scanf("%d", &n) != EOF){
        for (int i=0;i<n;i++){
            scanf("%d", &buf[i]);
        }

        sort(buf, buf+n, cmp);

        for (int i=0;i<n;i++){
            printf("%d ", buf[i]);
        }
        printf("\n");
    }
    return 0;
}

在 cmp 中,当它返回 true 时,表示 cmp 函数的第一个参数将会排在第二个参数之前。

在 sort() 中默认是以 < 来比较的,也就是升序,我们也可以重载 <。

  • 例2.2 成绩排序:
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
// 成绩 姓氏 年龄排序
// 重载运算符
struct E{
    char name[101];
    int age;
    int score;

    bool operator < (const E &b) const{        // 利用 c++ 运算符重载直接定义小于运算符
        if (score != b.score)
            return score < b.score;
        int tmp = strcmp(name, b.name);
        if (tmp != 0)
            return tmp < 0;
        else
            return age < b.age;
    }
}buf[1000];


int main(){
    int n;
    while (scanf("%d", &n) != EOF){
        for (int i=0;i<n;i++){
            scanf("%s%d%d", buf[i].name, &buf[i].age, &buf[i].score);
        }

        sort(buf, buf+n);

        for (int i=0;i<n;i++){
            printf("%s %d %d\n", buf[i].name, buf[i].age, buf[i].score);
        }
    }
    return 0;
}

日期类问题

在计算日期差值的问题中,我们进行预处理——空间换时间

#include<stdio.h>
#define ISYEAP(x) x%100 !=0 && x%4 == 0 || x%400 == 0?1:0

// 定义宏判断是否为闰年,方便计算天数
// 以空间换时间,将公元 0 - 5001 所有的天数保存下来

int dayOfMonth[13][2] = {
    0, 0,
    31, 31,
    28, 29,
    31, 31,
    30, 30,
    31, 31,
    30, 30,
    31, 31,
    31, 31,
    30, 30,
    31, 31,
    30, 30,
    31, 31
};

struct Date
{
    int Day;
    int Month;
    int Year;
    void nextDay(){
        Day ++;
        if (Day > dayOfMonth[Month][ISYEAP(Year)]){
            Day = 1;
            Month ++;
            if (Month > 12){
                Month = 1;
                Year ++;
            }
        }
    }
};

int buf[5001][13][32];

int Abs(int x){
    return x<0?-x:x;
}

int main(){
    Date tmp;
    int cnt = 0;
    tmp.Day = 1;
    tmp.Month = 1;
    tmp.Year = 0;

    while(tmp.Year != 5001){
        buf[tmp.Year][tmp.Month][tmp.Day] = cnt;
        tmp.nextDay();
        cnt ++;
    }

    int d1,m1,y1;
    int d2,m2,y2;
    while(scanf("%4d%2d%2d", &y1,&m1,&d1) != EOF){
        scanf("%4d%2d%2d", &y2,&m2,&d2);
        printf("%d\n", Abs(buf[y2][m2][d2] - buf[y1][m1][d1]) + 1);
    }
    return 0;
}

hash的应用

将存储位置与数据本身对应起来的手段就是 Hash。

统计同成绩学生的人数:

#include<stdio.h>
int main(){
    int n;
    while(scanf("%d", &n) != EOF && n!= 0){
        int Hash[101] = {0};

        for (int i=1;i<=n;i++){
            int x;
            scanf("%d", &x);
            Hash[x] += 1;
        }

        int x;
        scanf("%d", &x);

        printf("%d\n", Hash[x]);
    }
    return 0;
}

大数排序,选取前 m 大的数

#include<stdio.h>
#define OFFSET 500000

//hash数组输出前 m 大的数
int Hash[1000001] = {0};

int main(){
    int n,m;
    while(scanf("%d%d", &n, &m) != EOF){
        for (int i=1;i<=n;i++){
            int x;
            scanf("%d", &x);
            Hash[x+OFFSET] = 1;
        }

        for (int i=500000;i>=-500000;i--){
            if (Hash[i+OFFSET] ==1 ){
                printf("%d", i);
                m--;
                if (m!=0)
                    printf(" ");
                else{
                    printf("\n");
                    break;
                }
            }
        }
    }
    return 0;
}

注意由于输入数据出现了负数,所以需要对输入的数据加上一个固定的偏移值,使[-500000,500000] 映射到[0,100000]上。

排版题

对于所要求的图形不具有显著的规律性,我们需要先排版,然后再输出。

  • 例2.8:叠框
#include<stdio.h>
int main(){
    int outPutBuf[82][82];
    char a,b;
    int n;
    bool firstCase = true; //是否为第一组数据标志
    while (scanf("%d %c %c", &n, &a, &b) == 3){
        if (firstCase == true)
            firstCase = false;
        else
            printf("\n");
        for (int i=1, j=1;i<=n;i+=2,j++){
            int x=n/2+1, y=x;
            x-=j-1;y-=j-1;
            char c=j%2==1?a:b;
            for (int k=1;k<=i;k++){
                outPutBuf[x+k-1][y] = c;
                outPutBuf[x][y+k-1] = c;
                outPutBuf[x+i-1][y+k-1] = c;
                outPutBuf[y+k-1][x+i-1] = c;
            }
        }
        if(n!=1){
            outPutBuf[1][1] = ' ';
            outPutBuf[1][n] = ' ';
            outPutBuf[n][1] = ' ';
            outPutBuf[n][n] = ' ';
        }
        for (int i=1;i<=n;i++){
            for (int j=1;j<=n;j++){
                printf("%c", outPutBuf[i][j]);
            }
            printf("\n");
        }
    }
}

查找

###二分查找:需要先进行升序排序。

  • 例 2.10: 查找学生信息
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
struct Student{
    char no[100];
    char name[100];
    int age;
    char sex[5];
    bool operator < (const Student & A) const{
        return strcmp(no, A.no) < 0 ;
    }

}buf[1000];

int main(){
    int n;
    while (scanf("%d", &n) != EOF){
        for (int i=0; i<n;i++){
            scanf("%s%s%s%d", buf[i].no, buf[i].name, buf[i].sex, &buf[i].age);
        }
        sort(buf, buf+n);
        int t;
        scanf("%d", &t);
        while(t--!=0){
            int ans=-1;
            char x[30];
            scanf("%s", x);
            int top=n-1, base=0;
            while(top>=base){
                int mid = (top+base)/2;
                int tmp = strcmp(buf[mid].no, x);
                if (tmp==0){
                    ans=mid;
                    break;
                }
                else if(tmp>0)
                    top = mid-1;
                else
                    base = mid+1;

            }
            if(ans==-1){
                    printf("No Answer!\n");
            }
            else printf("%s %s %s %d\n", buf[ans].no, buf[ans].name, buf[ans].sex, buf[ans].age);

        }
    }
    return 0;
}

贪心算法

贪心是一种总是选择当前最好的选择,而不从整体上去把握的思想,但往往这种贪心策略能够得到接近最优的结果。但是贪心策略是否有效,需要我们从理论上证明,往往通过反证法。

  • 例2.11 FatMouse’s Trade:

我们的策略是每次都买性价比最高的物品,直到钱被耗尽或物品被买完。

#include<stdio.h>
#include<algorithm>
using namespace std;
struct goods{
    double mass;
    double value;
    double ratio;
    bool operator < (const goods &A) const{
        return ratio > A.ratio;
    }
}buf[1000];

int main(){
    double m;
    int n;
    while (scanf("%lf%d", &m, &n) != EOF){
        if (m==-1 & n==-1)
            break;
        for (int i=0;i<n;i++){
            scanf("%lf%lf", &buf[i].mass, &buf[i].value);
            buf[i].ratio = buf[i].mass / buf[i].value;
        }
        sort(buf, buf+n);
        double mount_mass = 0;
        int idx = 0;
        while (m > 0 && idx < n){
            if (buf[idx].value > m){
                mount_mass += m*buf[idx].ratio;
                break; 
            }
            else{
                m -= buf[idx].value;
                mount_mass += buf[idx].mass;
                idx ++;
            }
        }
        printf("%.3lf\n", mount_mass);
    }

    return 0;
}
  • 例2.12 今年暑假不 AC:

贪心策略是选择结束时间最早的。

#include<stdio.h>
#include<algorithm>
using namespace std;
struct program
{
    int startTime;
    int endTime;
    bool operator < (const program &A) const{
        return endTime < A.endTime;
    }
}buf[100];

int main(){
    int n;
    while (scanf("%d", &n) != EOF){
        if (n==0)
            break;
        for (int i=0;i<n;i++){
            scanf("%d%d", &buf[i].startTime, &buf[i].endTime);
        }
        sort(buf, buf+n);
        int currentTime = 0;
        int countProgram = 0;
        for (int i=0;i<n;i++){
            if (currentTime <= buf[i].startTime){
                countProgram ++;
                currentTime = buf[i].endTime;
            }
        }
        printf("%d\n", countProgram);
    }
    return 0;
}

文章作者: lovelyfrog
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 lovelyfrog !
 上一篇
机试-数据结构 机试-数据结构
一.栈的应用堆栈是一种数据项按序排列的数据结构,使用 stack 标准模版需要加上头文件 #include ,并使用标准命名空间。 用 stack S,定义一个保存元素类型为int的堆栈 S S.push(i) 向堆栈中压进一个数值为
2018-07-15
下一篇 
纪念外婆 纪念外婆
谨以此文纪念我逝去的外婆。 说外婆有点不习惯,在我们家那边,把外婆叫做舅奶。 舅奶去年刚过完八十大寿,我也不知道从什么时候,身体就开始变得不好了,今年过年的时候还是挺精神的,虽然没有以前那么精神,不能长时间的走路,躺在床上的时候也多了一
2018-07-04
  目录