杭电2016年计算机复试真题

注意:此复试题目是根据CSDN博客逃离地球的小小呆上发布的回忆版整理复原。为了恢复试题的原貌,我根据试题要求进行合理的脑补,按照oj系统的风格补全了试题的Problem Description、Input、Output、Sample Input、Sample Out等内容,并加入了详解、具体的代码实现。因为是复原版,不能保证当时的题目就是这么呈现的,也不能说明考场上的试题就是oj风格叙述的,仅供大家参考。有什么错误、不合理的地方欢迎指出。
原创不易,还请大家多支持

第一题

Problem Description

输入一个数N,判断其是否是素数(0,1,负数都是非素数)

Input

测试数据有多组,每组输入一个数 n。

Output

对于每组输入,若是素数则输出 yes,否则输入 no。

Sample Input

15
10007

Sample Output

no
yes

对于判断一个数是不是素数,我们不需要从2遍历到n依次判断是否可以被整除。而只需从2测试到不比 sqrt(n)(对 n 开根号)大的整数即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <math.h>

bool jude(int x) {
if (x <= 1) return false;//若小于1,必不是素数
int bound = (int)sqrt(x) + 1;//枚举上界,愿多枚举一个数也不能少枚举一个数
for (int i = 0; i < bound; i++)
if (x%i==0)//若能除尽,必不是素数
return false;
return true;//否则,是素数
}
int main() {
int n;
while (scanf("%d",&n)!=EOF)
puts(jude(n) ? "yes" : "no");
return 0;
}

还有一种思路叫做素数筛法,搜索中去除掉2的倍数,去除掉3的倍数,去除掉5的倍数等等…即把所有素数的倍数全部标记为非素数(可以到《王道论坛计算机考研机试指南》第四章第六节具体了解素数筛法)。这样一来我就就可以通过标记来判断一个数是否为素数。这种方法适用于求解某一范围内的所有素数,例如求1-10000中的所有素数。而就本题而言,仅需判断一个数是否是素数就没有必要利用素数筛法了。

第二题

Problem Description

在一个二维平面内有n个点,每个点坐标为(x,y),求最近的两点的距离。

Input

测试数据有多组,每组输入中有一个数字n,表示平面上共有n个点。接下来有n行,每行代表一个坐标x和y,用空格隔开

Output

输出最近的两个点之间的距离,结果保留两位小数。对于每组输入,输出一行

Sample Input

5
1 2
100 200
1000 2000
1000 1
1 3

Sample Output

1.00
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include <math.h>
#include <algorithm>
using namespace std;
struct Point//点结构
{
int x;
int y;
double getDistance(Point a) {
return (double)sqrt((a.x - x) * (a.x - x) + (a.y - y) * (a.y - y));
}
}points[100];
int main()
{
int n;
int cnt = 0;//所有应计算的距离数
double dis[50];//记录所有点的距离
while (scanf("%d", &n) != EOF)
{
for (int i = 0; i < n; i++)//输入数据
scanf("%d%d", &points[i].x, &points[i].y);
for (int i = 0; i < n; i++)
for (int j = i+1; j < n; j++)
dis[cnt++] = points[i].getDistance(points[j]);
sort(dis, dis + cnt);
printf("%.2lf\n", dis[0]);
}
}

这道题没什么难点,就是输入完点的数据之后暴力遍历所有的点,两两之间分别求距离,并保存在一个数组中。计算完成后把这个数组中的数据升序排列,输出第一个元素就是我们需要的答案

第三题

Problem Description

有一个文件记录了学生期末考试的几门成绩和学号,求出这几门课程的总分,并按照总分排序,从高到底,如果成绩相同,按照学号从小到大的顺序。

Input

数据从文件读入。第一行是表头,接下来数行每一行表示一个学生的数据,个数据字段用tab隔开

Output

输出学生按成绩按倒序排序后的姓名,每个名字用一个空格隔开

Sample Input

姓名 学号 语文 数学 英语
A 1 20 40 40
B 2 30 39 31
C 3 99 5 5

Sample Output

B C A

这道题是2010年第三题的升级版,但是2010年的那道题并没有说明若成绩相同按什么顺序继续排序。要实现两个关键字的排序,我们只需在之前的基础上修改<重载函数就可以了,当两个学生的成绩相等时按照学号的升序排序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <stdio.h>
#include <algorithm>
using namespace std;
struct Student//学生结构
{
char name[20];
int id;
int chinese;
int math;
int english;
int score;
void sum() {//成绩求和
score = chinese + math + english;
}
bool operator < (const Student& b) const { //利用C++算符重载直接定义小于运算符
if (score == b.score)//若两人分数相等
return id < b.id;
else
return score > b.score;//从高到低排序,若当前分数高则返回true
}
}students[100];
int main()
{
FILE* fp = NULL;
char buff[255];
fp = fopen("test1.txt", "r");//打开文件,打开方式为只读
char temp[100];
fgets(temp, 1000, fp);//跳过第一行
int n = 0;
while (fscanf(fp, "%s", &students[n].name) != EOF)
{
fscanf(fp, "%d", &students[n].id);
fscanf(fp, "%d", &students[n].chinese);
fscanf(fp, "%d", &students[n].math);
fscanf(fp, "%d", &students[n].english);
students[n].sum();//对成绩求和
n++;
}
sort(students, students + n);
for (int i = 0; i < n; i++)
printf("%s ", &students[i].name);
printf("\n");
}

第四题

Problem Description

有一个由数字组成的二维矩阵,大小为N*M;还有一个大小为n*m小二维矩阵。现在,将小矩阵放在大矩阵的某个位置,并以小矩阵左上角在大矩阵的位置作为起始坐标。我们把这两个二维矩阵对应位置上的数字绝对值之差加起来记为s,求s的最小值,并求出对应的起始坐标。

Input

输入共有四部分,第一部分有两个数字N、M,分别表示大矩阵有N行M列。第二部分有N行,是大矩阵的元素。第三部分也有两个数字n、m(n<=N,m<=M),分别代表小矩阵有n行m列。第四部分有n行,是小矩阵的元素。

Output

输出大矩阵与小矩阵对应元素绝对值差的和s,并输出起始坐标

Sample Input

4 4
1 2 3 4
4 5 6 8
1 2 3 4
5 6 7 8
2 2
2 2
4 5

Sample Output

1 (1,1)

这道题我并没有想到什么好的解决方法,只能靠暴力遍历枚举来求其解。先从大矩阵的左上角(1,1)出发,将小矩阵置于此,求出对用位置元素差绝对值的和,并用一个数组results保存起来,然后依次从左到右从上到下遍历所有的情况,即起始坐标从(1,1)~(N-n+1,M-m+1)。之后使用sort排序数组results,最后results[0]中的元素即我们所求。此算法时间复杂度为O((N-n)*(M-m)*n*m),实在没想到什么好办法,DFS也没思路。各位大神有什么巧妙的做法可以在评论区贴出来一起学习~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <stdio.h>
#include <math.h>
#include <algorithm>
using namespace std;
struct Result//结果结构
{
int diff;
int x;
int y;
bool operator < (const Result& b) const { //利用C++算符重载直接定义小于运算符
return diff < b.diff;
}
}results[100];
int Matrix1[101][101];
int Matrix2[101][101];
int main()
{
int N, M, n, m;
int cnt = 0;//计数器
scanf("%d%d", &N, &M);
for (int i = 1; i <= N; i++)//给大矩阵赋值
for (int j = 1; j <= M; j++)
scanf("%d", &Matrix1[i][j]);
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)//给小矩阵赋值
for (int j = 1; j <= m; j++)
scanf("%d", &Matrix2[i][j]);
for (int i = 1; i <= M - m + 1; i++)//开始暴力遍历两个矩阵,求其差绝对值的和
{
for (int j = 1; j <= N - n + 1; j++)
{
int temp = 0;
for (int k = 0; k < n; k++)
for (int h = 0; h < m; h++)
temp += abs(Matrix1[i + k][j + h] - Matrix2[k + 1][h + 1]);//累加此种情况差绝对值的和
results[cnt].diff = temp;
results[cnt].x = i;
results[cnt].y = j;
cnt++;
}
}
sort(results, results + cnt);
printf("%d (%d,%d)\n", results[0].diff, results[0].x, results[0].y);
}
文章作者: Teily
文章链接: https://teily.cn/article/HDU2016.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 TeilyMa's Blog