3.31实验室二面题解

小车问题

洛谷P1258 小车问题

题目描述

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

输入格式

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

输出格式

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

样例 #1

样例输入 #1
120 5 25
样例输出 #1
9.600000

提示

数据规模与约定

对于 100 % 100\% 100% 的数据,保证 0 ≤ s , a , b ≤ 1 0 9 0 \leq s, a, b \leq 10^9 0s,a,b109

考察知识点

小学奥数题

解题思路

  • 求解两人同时达到的最短时间,先让甲步行,乙先乘车前进,而后小车折返回来接甲,最后同时到达终点。
  • 当车行走 x x x米后将乙放下,而后返回来接甲,则这段距离时间即为 2 ∗ x / ( n + m ) 2*x/(n + m) 2x/(n+m) 而后甲乘车,乙步行,两人同时到达终点。
  • 这段时间也是乙步行至终点的时间,即 ( s − x ) / n (s-x)/n sx/n
  • 结合两个式子即可求出 x = ( 2 ∗ n ∗ s ) / ( m + 3 ∗ n ) x=(2 * n * s)/(m+3*n) x=(2ns)/(m+3n) ,最后即可得到结果。

代码实现

#include <stdio.h>

int main() {
	double s, n, m;
	scanf("%lf %lf %lf", &s, &n, &m);//使用双精度浮点型记录数据,便于运算
	double x = 0;
	x = (2 * n * s) / (m + 3 * n);
	double sum = x / n + (s - x) / m;
	printf("%.6lf", sum);
	return 0;
}

[NOIP2008 提高组] 笨小猴

题目链接:[NOIP2008 提高组] 笨小猴

题目描述

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

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

输入格式

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

输出格式

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

第二行是一个整数,如果输入单词是 Lucky Word,输出 maxn − minn \text{maxn}-\text{minn} maxnminn 的值,否则输出 0 0 0

样例 #1

样例输入 #1
error
样例输出 #1
Lucky Word
2

样例 #2

样例输入 #2
olympic
样例输出 #2
No Answer
0

提示

【输入输出样例 1 解释】

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

【输入输出样例 2 解释】

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

(本处原题面错误已经修正)

noip2008 提高第一题

提示

【输入输出样例 1 解释】

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

【输入输出样例 2 解释】

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

(本处原题面错误已经修正)

noip2008 提高第一题

考察知识点

质数,哈希表

解题思路

  • 这道题是一个简单的哈希表,故而先创建一个整型数组用于存放每个字母出现的次数。
  • 再遍历该整型数组,找到出现字母的最大值,最小值,作差。
  • 最后将差值放进判断质数的函数中,对返回值判断得出答案。

代码实现

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

int judge(int n)//判断是否为质数 {
	if (n < 2)
		return 0;
	if (n == 2 || n == 3)
		return n;
	for (int i = 2; i < n; i++) {
		if (n % i == 0)
			return 0;
		if (i == n - 1)
			return n;
	}
}

int main()
{
	char a[110];
	scanf("%s", a);
	int table[26];
	memset(table, 0, sizeof(table));//初始化数组,用于存放字幕出现的次数
	for (int i = 0; i < strlen(a); i++) {
		table[a[i] - 'a']++;
	}//每出现一次,记录该字母的元素加一
	int max = 0;
	int min = 999;
	for (int i = 0; i < 26; i++) {
		if (table[i] == 0)//为0说明不出现,不能作为最小值,跳过
			continue;
		if (table[i] < min)
			min = table[i];
		if (table[i] > max)
			max = table[i];
	}
	int n = max - min;
	int m = judge(n);
	if (m > 0) {
		printf("Lucky Word\n");
		printf("%d", m);
	}
	else {
		printf("No Answer\n");
		printf("%d",m);
	}
}

拯救oibh总部

题目链接:P1506拯救obih总部

题目描述

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

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

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

输入格式

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

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

输出格式

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

样例 #1

样例输入 #1
4 5
00000
00*00
0*0*0
00*00
样例输出 #1
1

样例 #2

样例输入 #2
5 5
*****
*0*0*
**0**
*0*0*
*****
样例输出 #2
5

提示

对于 100 % 100\% 100% 的数据, 1 ≤ x , y ≤ 500 1 \le x,y \le 500 1x,y500

解题思路

  • 本题使用DFS进行解答,本人现在还没学到这里,下次一定补上该块内容

代码实现

下次一定

队列安排

题目链接:P1160 队列安排

题目描述

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

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

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

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

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

输入格式

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

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

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

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

输出格式

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

样例 #1

样例输入 #1
4
1 0
2 1
1 0
2
3
3
样例输出 #1
2 4 1

提示

【样例解释】

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

2 1

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

2 3 1

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

2 3 4 1

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

2 4 1

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

最终队列:

2 4 1

【数据范围】

对于 20 % 20\% 20% 的数据, 1 ≤ N ≤ 10 1\leq N\leq 10 1N10

对于 40 % 40\% 40% 的数据, 1 ≤ N ≤ 1000 1\leq N\leq 1000 1N1000

对于 100 % 100\% 100% 的数据, 1 < M ≤ N ≤ 1 0 5 1<M\leq N\leq 10^5 1<MN105

解题思路

  • 用数组模拟双向链表,每次输入k,p后判断插入位置,直接插入,当所有k,p输入完成后数组位置也判断完进行过确认。
  • 最后判断删除

代码实现

#include<stdio.h>
int n,m;
struct node{
	int l,r;
	int id;
}a[1000005];
int main(){
	scanf("%d",&n);
	for(int i=2;i<=n;i++) {//从第二行开始,将i号学生插到k号的一边 
		int k,p;
		scanf("%d %d",&k,&p);
		if (p == 1) {//插在右边 
			a[i].r=a[k].r;
			a[i].l=k; 
			a[a[k].r].l=i;
			a[k].r=i;
		}
		else{//插在左边 
			a[i].l=a[k].l;
			a[i].r=k;
			a[a[k].l].r=i;
			a[k].l=i;
		}
	}
	scanf("%d",&m);
	for(int i=1;i<=m;i++){
		int x;
		scanf("%d",&x);
		a[x].id=1;//标记要删除的人 
	}
	int now;
	for(int i=1;i<=n;i++) {
	    if(a[i].l==0&&a[i].id!=1)
	        now=i;
	}
	while(now){//如果now存在的话 
		if(a[now].id==0) printf("%d ",now);
		now=a[now].r;//下一个 
	}
	return 0;
}

T3 句子反转

题目链接:B3640 T3 句子反转

题目背景

请尽量在 30min 之内写完题目。这是指「写代码」的时间;「读题」时间不计算在内。

题目描述

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

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

举一个例子:

we choose TO go 2 the 123 moon

程序应当输出:

MOON 321 THE 2 GO to CHOOSE WE

输入格式

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

输出格式

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

样例 #1

样例输入 #1
we choose TO go 2 the 123 moon
样例输出 #1
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 % 100\% 100% 的数据,句子中包含的单词数量不超过 1000 1000 1000,每个单词长度不超过 6 6 6

考察知识点

字符串

解题思路

  • 首先先将字符串逆置过来,由于是一个英文句子,故可以以单词间空格作为判断节点。
  • 从后向前判断,每次遇到空格即判断空格下一个元素的大小写,若为大写则将其全部转化为小写输出,反之,全部转化为大写输出。
  • 若遇到非字母元素,则从后向前输出这一部分元素,从而将数字逆过来。

代码实现

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

int main() {
    char s[101000];
    gets(s);
    int left = strlen(s) - 1;
    int right = strlen(s) - 1;
    int i = left;
    while (i >= 0) {
            while (left >= 0 && s[left] != ' ') {//每次遇到空格就停下来输出
                left--;
            }
            int n = left;
            left++;
            while (left <= right) {
                if (s[right] >= '0' && s[right] <= '9') {
                    printf("%c", s[right]);
                    right--;
                }//数字直接逆序输出
                else if (s[right] >= 'a' && s[right] <= 'z') {
                    printf("%c", s[left] - 32);//转化为大写输出
                    left++;
                }
                else if (s[right] >= 'A' && s[right] <= 'Z') {
                    printf("%c", s[left] + 32);//转化为小写输出
                    left++;
                }
            }
            left = n - 1;
            right = n - 1;
            i = n;
            printf(" ");//每次输出一个空格间隔单词
    }
    return 0;
}

[NOIP2006 普及组]明明的随机数

题目链接:P1059 [NOIP2006 普及组] 明明的随机数

题目描述

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

输入格式

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

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

输出格式

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

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

样例 #1

样例输入 #1
10
20 40 32 67 40 20 89 300 400 15
样例输出 #1
8
15 20 32 40 67 89 300 400

提示

NOIP 2006 普及组 第一题
排序算法

解题思路

  • 本题给定一个无序数列,要求将其从小到大排序后去掉相同的数据,故而先对整个数组进行排序
  • 排序后定义一个变量为0,由于是一个从小到大的数组,遍历一遍判断元素是否与上一个元素相等,若相等,变量不变;若不想等,则变量加1,变量最后的值即为不同元素的个数
  • 最后输出数组同上,元素与上一个相同则不输出,不同则输出元素

代码实现

#include <stdio.h>

void bubble(int a[], int n) {
	for (int j = n - 1; j > 0; j--) {
		for (int i = 0; i <= j; i++) {
			if (a[i] > a[i + 1]) {
				int swap = a[i];
				a[i] = a[i + 1];
				a[i + 1] = swap;
			}
		}
	}
}

int main()
{
	int n;
	scanf("%d", &n);
	int a[1000] = { 0 };
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
	}
	bubble(a, n);//冒泡排序,从小到大排序数组	
	int m = n;
	for (int i = 1; i <= n; i++) {
		if (i >= 2) {
			if (a[i] == a[i - 1])
				m--;
		}
	}
	printf("%d\n", m);
	for (int i = 1; i <= n; i++) {
		if (i >= 2) {
			if (a[i] == a[i - 1])
				continue;
		}
		printf("%d ", a[i]);
	}
	return 0;
}

P3817 小A的糖果

题目链接:P3817 小A的糖果

题目描述

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

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

输入格式

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

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

输出格式

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

样例 #1

样例输入 #1
3 3
2 2 2
样例输出 #1
1

样例 #2

样例输入 #2
6 1
1 6 1 2 0 4
样例输出 #2
11

样例 #3

样例输入 #3
5 9
3 1 4 1 5
样例输出 #3
0

提示

样例输入输出 1 解释

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


样例输入输出 2 解释

第 2 盒糖吃掉 6 6 6 颗,第 4 盒吃掉 2 2 2 颗,第 6 盒吃掉 3 3 3 颗。


数据规模与约定
  • 对于 30 % 30\% 30% 的数据,保证 n ≤ 20 n \leq 20 n20 a i , x ≤ 100 a_i, x \leq 100 ai,x100
  • 对于 70 % 70\% 70% 的数据,保证 n ≤ 1 0 3 n \leq 10^3 n103 a i , x ≤ 1 0 5 a_i, x \leq 10^5 ai,x105
  • 对于 100 % 100\% 100% 的数据,保证 2 ≤ n ≤ 1 0 5 2 \leq n \leq 10^5 2n105 0 ≤ a i , x ≤ 1 0 9 0 \leq a_i, x \leq 10^9 0ai,x109

考察知识点

贪心算法

解题思路

  • 该题是一道贪心算法的问题,要让任意相邻两盘糖果数量小于目标值,则每次都先吃掉靠后一盘糖果
  • 当每次都先吃掉后一盘糖果,这样可以让下次判断时总数减小,达到吃最少糖果的目的

代码实现

#include <stdio.h>
int main() {
	long long a[100000];
	long long n, m;
	scanf("%lld %lld", &n, &m);
	for (int i = 0; i < n; i++) {
		scanf("%lld", &a[i]);
	}//输入数据
	long long j = 0;
	for (int i = 0; i < n - 1; i++) {
		int k = 0;
		if (a[i] + a[i + 1] <= m)//如果小于目标值,直接跳过该元素的判断
			continue;
		if (a[i] + a[i + 1] > m) {
			k = a[i] + a[i + 1] - m;//定义应该吃掉糖果的数量
			if (k <= a[i+1]) {//判断吃该元素下一盘能否满足要求
				a[i + 1] -= k;
				j += k;
			}
			else {
				a[i] = k - a[i + 1];
				a[i + 1] = 0;
				j += k;
			}
		}
	}
	printf("%lld", j);
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值