杭电2018年计算机复试真题

杭电 2018 年计算机复试真题

写在前面

此题目是根据 CSDN 博客粥粥同学发布的内容进行收集整理,记录了本人的解题过程和一些想法。仅供大家参考,如有错误,欢迎大家指出!


第一题

Problem Description

杭电实验室定期会集体去电影院看电影,按照惯例,每个成员需要先抽个号码。给出 n 个人的名字,各抽取一个数字,自己用一种数据结构存取人的名字和抽取数字信息(票数),例如:Bob9 Alice12 Tom5 Listen7 Nick4 1.1 定义一种数叫丑数,其因子除 1 外只用 2,3,5 的倍数(例如 4,10 是丑数,11,13 不是),输出所有抽到丑数人的名字 1.2 根据个人所抽数字大小升序排序,输出排序后的所有名字。 1.3 现有一个新名字加入,将名字插入所以名字中间(n/2)处,并输出排序后所有人的名字。

1.1

1.1 定义一种数叫丑数,其因子除 1 外只用 2,3,5 的倍数(例如 4,10 是丑数,11,13 不是),输出所有抽到丑数人的名字

Input

输入包含多个测试实例,首先是正整数 n,接着是 n 行,每行包含姓名与抽取数字信息(票数)

Output

输出所有抽到丑数人的名字

Sample Input

5 Bob 9 Alice 12 Tom 5 Listen 7 Nick 4

Sample Output

Bob Alice Tom Nick

解题思路

判断丑数,对 2,3,5 整除

参考源码

代码语言:javascript
复制
// 1.1
#include <algorithm>
#include <iostream>
using namespace std;
struct people {
    char name[20];
    int num;
} p[1000];
bool cmp(people a, people b) { return a.num < b.num; }  //升序
bool isugly(int a) {
    while (a % 2 == 0) a /= 2;
    while (a % 3 == 0) a /= 3;
    while (a % 5 == 0) a /= 5;
    if (a == 1) return true;
    return false;
}
int main() {
    int n;
    while (cin >> n) {
        getchar();
        for (int i = 0; i < n; i++) {
            cin >> p[i].name >> p[i].num;
        }
        sort(p, p + n, cmp);
        for (int i = 0; i < n; i++) {
            if (isugly(p[i].num)) cout << p[i].name << endl;
        }
    }
    return 0;
}
1.2

1.2 根据个人所抽数字大小升序排序,输出排序后的所有名字。

Input

输入包含多个测试实例,首先是正整数 n,接着是 n 行,每行包含姓名与抽取数字信息(票数)

Output

输出排序后的所有名字。

Sample Input

5 Bob 9 Alice 12 Tom 5 Listen 7 Nick 4

Sample Output

Nick Tom Listen Bob Alice

解题思路

sort()排序

参考源码

代码语言:javascript
复制
// 1.2
#include <algorithm>
#include <iostream>
using namespace std;
struct people {
    char name[20];
    int num;
} p[1000];
bool cmp(people a, people b) { return a.num < b.num; }  //升序
int main() {
    int n;
    while (cin >> n) {
        getchar();
        for (int i = 0; i < n; i++) {
            cin >> p[i].name >> p[i].num;
        }
        sort(p, p + n, cmp);
        for (int i = 0; i < n; i++) {
            cout << p[i].name << endl;
        }
    }
    return 0;
}
1.3

1.3 现有一个新名字加入,将名字插入所以名字中间(n/2)处,并输出排序后所有人的名字。

Input

输入包含多个测试实例,首先是正整数 n,接着是 n 行,每行包含姓名与抽取数字信息(票数),第 n+1 行是一个新名字加入,以及他的票数

Output

输出排序后的所有名字。

Sample Input

5 Bob 9 Alice 12 Tom 5 Listen 7 Nick 4 Emory 10

Sample Output

Bob Alice Emory Tom Listen Nick

解题思路

数组插入

参考源码

代码语言:javascript
复制
// 1.3
#include <iostream>
using namespace std;
struct people {
    char name[20];
    int num;
} p[1000], newp;
int main() {
    int n;
    while (cin >> n) {
        getchar();
        for (int i = 0; i < n; i++) {
            cin >> p[i].name >> p[i].num;
        }
        cin >> newp.name >> newp.num;
        for (int i = n - 1; i >= n / 2; i--) {
            p[i + 1] = p[i];
        }
        p[n / 2] = newp;
        for (int i = 0; i < n + 1; i++) {
            cout << p[i].name << endl;
        }
    }
    return 0;
}

第二题

Problem Description

关于某同学没赶上拍毕业照,现用一个算法将他的头像从一张老照片 P 到毕业照某位置,输入源头像起始位置和头像宽,将数据拷贝到目的图片某起始位置某宽度 很长而且有图,没办法全部写出来,大意是给出两张 bmp 图像(可以理解为两个矩阵),将第一张图上的某个部分截取下来放入第二张的某个位置 (把图 1 中的人头像截下来贴到图 2 的人头上),然后给出了接函数的定义和参数的定义,readbmp 读取图像,copybmp 复制图像等。 2.1 一道程序填空题,根据题目函数的定义填岀整个拷贝图像的过程,比较长,但很简单,基本送分题。 2.2 写出 copybmp 的整个具体函数 void copybmp(unsigned char *pOldbuf,unsigned char *pNewbuf,int OldW,int NewW,int BlockW,int BlockH) pOldbuf 和 pNewbuf 是两张图像首地址 OldW 和 NewW 是两图像宽度 BlockW 和 BlockH 是待截取部分的宽和高

解题思路

参考源码

代码语言:javascript
复制
void copybmp(unsigned char *pOldbuf,unsigned char *pNewbuf,int OldW,int NewW,int BlockW,int BlockH)

第三题

Problem Description

瓜农王大爷去年种西瓜赚了不少钱。看到收入不错,今年他又重新开辟了 n 个西瓜地。  为了能给他的 n 个西瓜地顺利的浇上水,对于每个西瓜地他可以选择在本地打井,也可以修管道从另一个瓜地(这个瓜地可能打了井;也可能没打井,他的水也是从其他瓜地引来的)将水引过来。  当然打井和修管道的费用有差别。已知在第 i 个西瓜地打井需要耗费 wi 元,在第 i、j 个西瓜地之间修管道需要耗费 pi,j 元。  现在的问题是:王大爷要想使所有瓜地都被浇上水,至少需要花费多少钱(打井与修管道的费用和)?  由于瓜地较多,王大爷无法选择在哪些(个)瓜地打井,哪些西瓜地之间修管道。  请你编程帮王大爷做出决策,求出最小费用。

Input

第一行为一个整数 n。接下来 n 行每行一个整数 wi,接下来 n 行,每行 n 个整数,第 i 行的第 j 个数,表示连接 i 号田和 j 号田需要的费用 P i,j ​ 1<=N<=300;1<=wi<=100000;p(i,i)=0;1<=p(i,j)=p(j,i)<=100000

Output

输出最小开销

Sample Input

6 5 4 4 3 1 20 0 2 2 2 9 9 2 0 3 3 9 9 2 3 0 4 9 9 2 3 4 0 9 9 9 9 9 9 0 9 9 9 9 9 9 0

Sample Output

19

解题思路

构图时,可以多加一个隐藏的点,这个点与打井的点相连,可以抽象为地下泉,打井时,实际上是在往地下连边,之后就是最小生成树问题,可以使用 Kruskal 算法

参考源码

代码语言:javascript
复制
#include <algorithm>
#include <iostream>
using namespace std;
int t = 0, ans = 0;
int fa[302], w[302];
struct edge {
    int from, to, c;
} E[100000];
int find(int x) {
    if (x == fa[x]) return x;
    return fa[x] = find(fa[x]);
}
bool cmp(edge a, edge b) { return a.c < b.c; }
int main() {
    int n, temp, num;
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> w[i];
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cin >> temp;
            if (i != j) {
                E[++t].from = i;
                E[t].to = j;
                E[t].c = temp;
            } else {  //加入打井的原点
                E[++t].from = 0;
                E[t].to = j;
                E[t].c = w[i];
            }
        }
    }
    for (int i = 0; i <= n; i++) {
        fa[i] = i;  //初始化并查集
    }
    sort(E + 1, E + t + 1, cmp);  //边权从小到大排序
    for (int i = 1; i <= t; i++) {
        int ff = find(E[i].from);  //寻找两个端点所在集合的根节点
        int ft = find(E[i].to);
        if (ff != ft) {     //若不在同一集合
            ans += E[i].c;  //累加
            fa[ff] = ft;    //加入集合
            num++;          //最小生成树边数+1
        }
        if (num == n) break;
    }
    cout << ans << endl;
    return 0;
}

相关内容

  • 杭电 2014 年计算机复试真题
  • 杭电 2015 年计算机复试真题
  • 杭电 2016 年计算机复试真题
  • 杭电 2017 年计算机复试真题
  • 杭电 2019 年计算机复试真题