移动应用开发实验室二面题解

第一题 小车问题

题目描述

甲、乙两人同时从 A 地出发要尽快同时赶到 B 地。出发时 A 地有一辆小车,可是这辆小车除了驾驶员外只能带一人。已知甲、乙两人的步行速度一样,且小于车的速度。问:怎样利用小车才能使两人尽快同时到达。

输入格式:

仅一行,三个实数,分别表示 AB 两地的距离 s,人的步行速度 a,车的速度 b。

输出格式:

两人同时到达 B 地需要的最短时间,保留 66 位小数。

输入输出样例:

输入输出
120 5 259.600000

说明/提示:

数据规模与约定

对于 100%100% 的数据,保证 0≤s,a,b≤10e9

思路:

本题的难点在于找出题目中暗含的等量关系,找出等量关系后,题目就变成了简单的解方程问题。乘车问题一般从路程和时间两个角度考虑等量关系。甲、乙两人步行速度一样且同时赶到,因此甲、乙乘车和步行的时间与路程都应该相等,可以将整段路程s分成三个部分,分别是两段步行的x和一段乘车的s-2x。而在时间上,b步行x的时间与a乘车后车返回接a所用的时间相等,可得等式x/a=(s-x+s-2x)/b,解出x后,带入x的值求出时间即可。

代码:

#include<stdio.h>

int main() {
    double s, a, b;
    double x, t;
    scanf("%lf%lf%lf", &s, &a, &b);
    x = 2*s*a / (b + 3 * a);
    t = x / a + (s - x) / b;
    printf("%.6lf", t);
}

第二题 笨小猴

题目描述:

笨小猴的词汇量很小,所以每次做英语选择题的时候都很头疼。但是他找到了一种方法,经试验证明,用这种方法去选择选项的时候选对的几率非常大!

这种方法的具体描述如下:假设 maxn 是单词中出现次数最多的字母的出现次数,minn 是单词中出现次数最少的字母的出现次数,如果 maxn−minn 是一个质数,那么笨小猴就认为这是个 Lucky Word,这样的单词很可能就是正确的答案。

输入格式:

一个单词,其中只可能出现小写字母,并且长度小于 100。

输出格式:

共两行,第一行是一个字符串,假设输入的的单词是 Lucky Word,那么输出 Lucky Word,否则输出 No Answer

第二行是一个整数,如果输入单词是 Lucky Word,输出 maxn−minnmaxn−minn 的值,否则输出 00。

输入输出样例:

输入输出
error
Lucky Word
2
olympic
No Answer
0

说明/提示:

【输入输出样例 1 解释】

单词 error 中出现最多的字母 r 出现了 3 次,出现次数最少的字母出现了 1 次,3−1=2,2 是质数。

【输入输出样例 2 解释】

单词 olympic 中出现最多的字母 i 出现了 1 次,出现次数最少的字母出现了 1 次,1−1=0,0 不是质数。

思路:

对字符串进行两次遍历,一次比较字符串中的每一个字符,并声明两个变量依次存放字符存在次数的最大值和最小值,再用一个变量存放最值之间的差值,并判断差值是否为质数即可求解。

代码:

#include<stdio.h>

int main() {
	int maxn = -1, minn = 101, cnt = 0;
	int s, flag = 1;
	char word[100];
	scanf("%s", word);
	for (int i = 0; word[i]; i++) {
		cnt = -1;
		for (int j = 0; word[j]; j++) {
			if (word[j] == word[i]) {
                cnt++;
            }
		}
		if (cnt < minn) {
            minn = cnt;
        }
		if (cnt > maxn) {
            maxn = cnt;
        }
	} //遍历字符串得到最大值和最小值
	s = maxn - minn;
	if (s == 1 || s==0) {
		flag = 0;
	}
	for (int i = 2; i < s; i++) {
		if (s % i == 0) {
			flag = 0;
			break;
		}
	} //判断是否为质数
	if (flag == 1) {
        printf("Lucky Word\n%d", s);
    } else {
        printf("No Answer\n0");
    }
}

第三题 拯救oibh总部

题目描述:

oibh 被突来的洪水淹没了,还好 oibh 总部有在某些重要的地方起一些围墙。用 * 号表示,而一个四面被围墙围住的区域洪水是进不去的。

oibh 总部内部也有许多重要区域,每个重要区域在图中用一个 0 表示。

现在给出 oibh 的围墙建设图,问有多少个没被洪水淹到的重要区域。

输入格式:

第一行为两个正整数 x,y。

接下来 x 行,每行 y 个整数,由 * 和 0 组成,表示 oibh 总部的建设图。

输出格式:

输出没被水淹没的 oibh 总部的 0 的数量。

输入输出样例:

输入输出
4 5
00000
00*00
0*0*0
00*00
1
5 5
*****
*0*0*
**0**
*0*0*
*****
5

说明/提示:

对于 100% 的数据,1≤x,y≤500。

思路:

这道题如果直接遍历二维数组,无法判断哪些位置的0被“*”围起来了,除非所有“0”都在“*”围成的围墙中,因此考虑使用深度优先搜索。在输入数据后,分别从第一行和最后一行以及第一列和最后一列进行深度优先搜索,并将搜索到的“0”标记为“*”,“*”即为不可通行的区域。在搜索完成后,再对数组进行遍历,统计数组中存在多少个"0"即可。

代码:

#include<stdio.h>
#include<stdlib.h>

int n, m;
char map[500][500];
int location[4][2] = { {-1, 0}, {1, 0}, {0, 1}, {0, -1} };

int Check(int x, int y) {
	if (x >= 0 && x < n && y >= 0 && y < m) {
		return 1;
	}
	return 0;
} //判断当前位置是否到达边界

void DFS(int x, int y) {
	int tx, ty;
	if (Check(x, y) == 0) {
		return 0;
	}
	if (map[x][y] == '*') {
		return 0;
	} //结束边界判断
	map[x][y] = '*';
	for (int i = 0; i < 4; i++) {
		tx = x + location[i][0];
		ty = y + location[i][1];
		DFS(tx, ty);
	} //继续向下一个位置搜索
	return 0;
} //深度搜索函数

int main() {
	int sum = 0;
	scanf("%d%d", &n, &m);
	for (int i = 0; i < n; i++) {
		scanf("%s", map[i]);
	}
	if (n > 1) {
		for (int j = 0; j < m; j++) {
			DFS(0, j);
			DFS(n-1, j);
		} //如果只有一行,则只需搜索这一行
	} else {
		for (int j = 0;j < m; j++) {
			DFS(0, j);
		}
	} //对第一行和最后一行进行深度优先搜索
	for (int i = 1; i < n - 1; i++) {
		DFS(i, 0);
		DFS(i, m-1);
	} //对一列和最后一列进行深度优先搜索
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			if (map[i][j] == '0') {
				sum++;
			}
		}
	} //遍历统计“0”的个数
	printf("%d", sum);
	return 0;
}

第四题 队列安排

题目描述:

一个学校里老师要将班上 N 个同学排成一列,同学被编号为 1∼N,他采取如下的方法:

  1. 先将 1 号同学安排进队列,这时队列中只有他一个人;

  2. 2∼N 号同学依次入列,编号为 i 的同学入列方式为:老师指定编号为 i 的同学站在编号为 1∼(i−1) 中某位同学(即之前已经入列的同学)的左边或右边;

  3. 从队列中去掉 M 个同学,其他同学位置顺序不变。

在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。

输入格式:

第一行一个整数 N,表示了有 N 个同学。

第 2∼N 行,第 i 行包含两个整数 k,p,其中 k 为小于 i 的正整数,p 为 0 或者 1。若p 为 0,则表示将 i 号同学插入到 k 号同学的左边,p 为 1 则表示插入到右边。

第 N+1 行为一个整数 M,表示去掉的同学数目。

接下来 M 行,每行一个正整数 x,表示将 x 号同学从队列中移去,如果 x 号同学已经不在队列中则忽略这一条指令。

输出格式:

一行,包含最多 N 个空格隔开的整数,表示了队列从左到右所有同学的编号。

输入输出样例:

输入输出
4
1 0
2 1
1 0
2
3
3
2 4 1

说明/提示:

【样例解释】

将同学 2 插入至同学 1 左边,此时队列为:

2 1

将同学 3 插入至同学 2 右边,此时队列为:

2 3 1

将同学 4 插入至同学 1 左边,此时队列为:

2 3 4 1

将同学 3 从队列中移出,此时队列为:

2 4 1

同学 3 已经不在队列中,忽略最后一条指令

最终队列:

2 4 1

【数据范围】

对于 20% 的数据,1≤N≤10。

对于 40% 的数据,1≤N≤1000。

对于 100% 的数据,1<M≤N≤105。

思路:

这道题要对一个队列实现插入、删除,并且要插入在元素的前后任意位置,在插入和删除的过程中其实隐含了大量对元素的查找操作,可以考虑使用数组来模拟双向链表实现题目要求的操作。

代码:

#include<stdio.h>
#include<stdlib.h>

int pre[100005];
int next[100005];
int nums[100005] = { 0 };

int main() {
	int n;
	scanf("%d", &n);
	next[0] = 1; //"1"为第一个数
	pre[0] = n; //“n”为最后一个数
	next[1] = 0; //“1”之后暂时没有任何数
	pre[1] = 0; //“1”为第一个数
	int k, p;
	for (int i = 2; i <= n; i++) {
		scanf("%d%d", &k, &p);
		if (p == 0) {
			next[i] = k;
			pre[i] = pre[k];
			next[pre[i]] = i;
			pre[k] = i;
		} else {
			next[i] = next[k];
			pre[next[k]] = i;
			next[k] = i;
			pre[i] = k;
		}
	} //插入元素
	int m, x;
	scanf("%d", &m);
	while (m--) {
		scanf("%d", &x);
		if (nums[x] == 0) {
			next[pre[x]] = next[x];
			pre[next[x]] = pre[x];
			nums[x] = 1;
		}
	} //删除元素
	int i = next[0];
	while (i != 0) {
		printf("%d ", i);
		i = next[i];
	} //打印元素
}

第五题 句子反转

题目描述:

给定一行句子,每个词之间用空格隔开,要么是全小写英文单词,要么是全大写英文单词,要么是自然数。

要求将这些单词倒序输出。而且对于每个单词,如果是小写词,应当转为大写;如果是大写词,应当转为小写;如果是自然数,应该倒转输出。

输入格式:

仅一行,即需要反转的句子。

输出格式:

仅一行,表示程序对句子的处理结果。

输入输出样例:

输入输出
we choose TO go 2 the 123 moon
MOON 321 THE 2 GO to CHOOSE WE

说明/提示:

样例解释

首先应当按单词逆序,即:

moon 123 the 2 go TO choose we

小写变大写、大写变小写、倒转自然数之后,得到最终结果:

MOON 321 THE 2 GO to CHOOSE WE

数据规模与约定

对于 100% 的数据,句子中包含的单词数量不超过 1000,每个单词长度不超过 6。

思路:

该题要求将字符串倒转并转换大小写,但这里的倒转并不意味着将字符倒转输出,而是将单词的顺序倒转输出,因此,可以用两个整型变量模拟字符指针,来实现题目所要求的操作。

代码:

#include<stdio.h>
#include<string.h>

int main() {
	int m, n;
	char ch[6050];
	fgets(ch,6050,stdin);
	m = strlen(ch) - 1;
	n = strlen(ch) - 1; //让m、n指向字符串末尾
	while (m > 0) {
		while (m > 0 && ch[m] != ' ') {
			m--; //让m指向每一个单词前的空格处
            }
		if (ch[m + 1] <= 'Z' && ch[m + 1] >= 'A' || ch[m + 1] <= 'z' && ch[m + 1] >= 'a') {
			if (m > 0) {
				if (ch[m + 1] <= 'Z' && ch[m + 1] >= 'A') {
					for (int i = m + 1; i <= n; i++) {
						ch[i] = ch[i] + 'a' - 'A';
						printf("%c", ch[i]);
					}
				} else {
					for (int i = m + 1; i <= n; i++) {
						ch[i] = ch[i] + 'A' - 'a';
						printf("%c", ch[i]);
					}
				}
			} else {
				if (ch[m] <= 'Z' && ch[m] >= 'A') {
					for (int i = m; i <= n; i++) {
						ch[i] = ch[i] + 'a' - 'A';
						printf("%c", ch[i]);
					}
				} else {
					for (int i = m; i <= n; i++) {
						ch[i] = ch[i] + 'A' - 'a';
						printf("%c", ch[i]);
					}
				}
			} //如果字符为字母,利用ASCII码实现大小写转换,并以单词为单位按顺序输出
		} else {
			if (m > 0) {
				for (int i = n; i > m; i--) {
					printf("%c", ch[i]);
				}
			} else {
				for (int i = n; i >= m; i--) {
					printf("%c", ch[i]);
				}
			}
		}  //如果字符为数字,逆序输出
		if (m > 0) {
			printf(" ");
		} //在单词间输出空格
			m--;
			n = m;
	} //让m、n指向前一个单词的末尾
	return 0;
}

第六题 明明的随机数

题目描述:

明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了 N 个 1 到 1000 之间的随机整数 (N≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。

输入格式:

输入有两行,第 1 行为 1个正整数,表示所生成的随机数的个数 N。

第 2 行有 N 个用空格隔开的正整数,为所产生的随机数。

输出格式:

输出也是两行,第 1 行为 1 个正整数 M,表示不相同的随机数的个数。

第 2 行为 M 个用空格隔开的正整数,为从小到大排好序的不相同的随机数。

输入输出样例:

输入输出
10
20 40 32 67 40 20 89 300 400 15
8
15 20 32 40 67 89 300 400

说明/提示:

思路:

这道题我采用的是桶的方法,申请三个数组arr,brr,crr,对第一个数组遍历,假设存在数字a,则brr[a]=1,并让统计变量自增。这样的话,重复的元素也只会记录一次。然后再对作为桶的数组brr遍历,如果brr[a]=1,则将a赋值到crr数组中。最后直接输出crr数组中的数据,得到的就是去重且排序完后的数据。

代码

#include<stdio.h>

int main() {
	int n, k = 0, cnt = 0;
	int arr[100] = { 0 }, brr[1001] = { 0 }, crr[100];
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		scanf("%d", &arr[i]);
	}
	for (int i = 0; i < n; i++) {
		if (arr[i] != 0) {
			int t = arr[i];
			if (brr[t] == 0) {
                cnt++;
            }
			brr[t] = 1;
		}
	} //将数据记录进“桶”中
    for (int j = 0; j < 1001; j++) {
		if (brr[j] == 1) {
			crr[k] = j;
			k++;
		}
	} //将桶中的数据赋到新数组中
	printf("%d\n", cnt);
	for (int i = 0; i < cnt; i++) {
		if (i != 0) {
            printf(" ");
        }
		printf("%d", crr[i]);
	} //打印新数组
}

第七题 小A的糖果

题目描述:

小 A 有 n 个糖果盒,第 i 个盒中有 ai​ 颗糖果。

小 A 每次可以从其中一盒糖果中吃掉一颗,他想知道,要让任意两个相邻的盒子中糖的个数之和都不大于 x,至少得吃掉几颗糖。

输入格式:

输入的第一行是两个用空格隔开的整数,代表糖果盒的个数 n 和给定的参数 x。

第二行有 n 个用空格隔开的整数,第 i 个整数代表第 i 盒糖的糖果个数 ai​。

输出格式:

输出一行一个整数,代表最少要吃掉的糖果的数量。

输入输出样例:

输入输出
3 3
2 2 2
1
6 1
1 6 1 2 0 4
11
5 9
3 1 4 1 5
0

说明/样例:

样例输入输出 1 解释

吃掉第 2 盒中的一个糖果即可。


样例输入输出 2 解释

第 2 盒糖吃掉 66 颗,第 4 盒吃掉 22 颗,第 6 盒吃掉 33 颗。


数据规模与约定

  • 对于 30% 的数据,保证 n≤20,ai​,x≤100。
  • 对于 70% 的数据,保证 n≤10e3,ai​,x≤105。
  • 对于 100% 的数据,保证 2≤n≤10e5,0≤ai​,x≤109。

思路:

该题可采用贪心算法求解,一对元素中,改变第一个只会使第一对组合符合要求,但如果改变第二个,便可以使得相邻三个元素到符合要求,所以尽量改变每一对中的第二个元素。

代码:

#include<stdio.h>

int main() {
	int n, x;
	long long sum=0;
	long long arr[100010];
	scanf("%d%d", &n, &x);
	for (int j = 1; j <= n; j++) {
		scanf("%lld", &arr[j]);
		if (arr[j] + arr[j - 1] > x) {
			int k = arr[j];
			arr[j] = x - arr[j - 1];
			sum += k - arr[j];
		}
	}
	printf("%lld", sum);
}


  

  • 9
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值