第1题:课程冲突
小 A 修了 n 门课程, 第 i 门课程是从第 ai 天一直上到第 bi 天。
定义两门课程的冲突程度为 : 有几天是这两门课程都要上的。
例如 a1=1,b1=3,a2=2,b2=4 时, 这两门课的冲突程度为 2。
现在你需要求的是这 n 门课中冲突程度最大的两门课的冲突程度。
时间限制:1000
内存限制:65536
输入
第一行一个正整数 n 表示课程数量。接下来 n 行,每行两个正整数 ai,bi。 2 ≤ n≤ 1000, 1 ≤ai ≤bi ≤ 1000。
输出
输出一个整数表示最大的冲突程度。
样例输入
3
1 3
2 4
5 5
样例输出
2
题目要求找出n门课程中冲突程度最大的两门课的冲突程度。冲突程度表示有几天是这两门课程都要上的。
解题思路:
(1)创建一个长度为1001的数组conflict,用于记录每一天有几门课程要上。
(2)遍历每一门课程,对于每门课程的时间范围[a, b],将conflict[a]~conflict[b]的值都加1,表示这些天有一门课程要上。
(3)遍历conflict数组,找到冲突程度最大的值,即为最大的冲突程度。
下面是使用C语言编写的解题代码:
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
int conflict[1001] = {0}; // 记录每一天的冲突程度
int i;
for (i = 0; i < n; i++) {
int a, b;
scanf("%d %d", &a, &b);
int j;
for (j = a; j <= b; j++) {
conflict[j]++;
}
}
int maxConflict = 0;
for (i = 1; i <= 1000; i++) {
if (conflict[i] > maxConflict) {
maxConflict = conflict[i];
}
}
printf("%d\n", maxConflict);
return 0;
}
在上述代码中,我们首先创建一个长度为1001的数组 conflict
,用于记录每一天的冲突程度。初始时,数组中所有元素都为0。
然后,我们使用一个循环遍历每一门课程。对于每门课程的时间范围 [a, b]
,我们将 conflict[a]
到 conflict[b]
的值都加1,表示这些天有一门课程要上。
接下来,我们再次遍历 conflict
数组,找到冲突程度最大的值,即为最大的冲突程度。
最后,我们将结果输出。
编译并运行上述代码,即可得到最大的冲突程度。
第2题:42点
42是:
· 组合数学上的第5个卡特兰数
· 字符’*‘的ASCII码
· 钼的原子序数
· 6与9的乘积结果的13进制表示
· 生命、宇宙以及任何事情的终极答案
· 以及……表达式(1+5)/2*(6-4)*7的值
因此,小机器人Marvin发明了这个叫42点的小游戏。在这个游戏中,玩家会获得n个数。玩家需要使用’+‘、’-‘、’*‘、’/‘、’(‘、’)'以及这n个数构成一个合法的中缀表达式,并使得该表达式的值为42。n个数之间的顺序可以改变。表达式运算过程中只能出现整数。
由于过于抑郁,Marvin无力完成这个游戏,于是来找你帮忙。你的任务是对于给定的n个数,判断他们是否能根据上述游戏规则算出42。
时间限制:1000
内存限制:65536
输入
第一行为一个数n,1<=n<=6。 第二行为n个数,每个数均为[1,13]范围内的整数
输出
输出一行,若可以算出42则输出“YES”,否则输出“NO”(注意大小写)
样例输入
6
1 5 2 6 4 7
样例输出
YES
为了解决这个问题,我们可以使用回溯法来尝试所有可能的表达式组合。下面是使用C语言编写的解题代码:
#include <stdio.h>
#include <stdbool.h>
bool canGet42(int nums[], int count, int sum) {
if (count == 0) {
if (sum == 42) {
return true; // 当前表达式的结果等于42
} else {
return false; // 当前表达式的结果不等于42
}
}
// 尝试将当前数字加入表达式并递归调用
if (canGet42(nums + 1, count - 1, sum + nums[0])) {
return true;
}
// 尝试将当前数字减去表达式并递归调用
if (canGet42(nums + 1, count - 1, sum - nums[0])) {
return true;
}
// 尝试将当前数字乘以表达式并递归调用
if (canGet42(nums + 1, count - 1, sum * nums[0])) {
return true;
}
// 如果当前数字不为0且能整除表达式,则尝试将当前数字除以表达式并递归调用
if (nums[0] != 0 && sum % nums[0] == 0 && canGet42(nums + 1, count - 1, sum / nums[0])) {
return true;
}
return false; // 无法得到42
}
bool canGet42Wrapper(int nums[], int count) {
int sum = 0;
return canGet42(nums, count, sum);
}
int main() {
int n;
scanf("%d", &n);
int nums[6];
for (int i = 0; i < n; i++) {
scanf("%d", &nums[i]);
}
if (canGet42Wrapper(nums, n)) {
printf("YES\n"); // 可以得到42
} else {
printf("NO\n"); // 无法得到42
}
return 0;
}
在上述代码中,我们定义了 canGet42
函数来实现回溯法。函数中,我们首先检查剩余可用的数字个数是否为0,如果是,则检查当前表达式的结果是否等于42。如果是,返回 true
;否则,返回 false
。
然后,我们使用递归调用来尝试将当前数字加入、减去、乘以、除以表达式,并对剩余数字进行递归调用。在递归调用之前,我们将当前数字与表达式的结果进行相应的运算,并将剩余数字列表和数字个数进行更新。在递归调用之后,我们返回递归调用的结果。
在 main
函数中,我们首先读取输入的数字个数和数字列表。然后,我们调用 canGet42Wrapper
函数来判断是否可以得到42。如果可以,输出 “YES”;否则,输出 “NO”。
编译并运行上述的代码可以解决该问题。你可以使用 C 语言编译器将代码保存为 .c
文件,然后编译并运行该文件来获取结果。
请注意,该代码使用了递归,可能在数字个数较大时会导致栈溢出。由于题目中给定的数字个数最多为 6,这不会成为问题。但如果需要处理更多的数字,可能需要使用其他方法,如动态规划。
第3题:最长下坡
小明天天沿着未名湖环湖路跑,有时候也觉得蛮累。
累的时候跑下坡就很开心。小明想知道最长的一段下坡有多长。
环湖路是个圆形,周长n米。每隔一米测一下路面高度,两个测高点之间的高度是单调变化或不变的。
问最长的一段下坡有多少米长。小明只能顺时针跑。下坡必须高度单调减少。
时间限制:1000
内存限制:65536
输入
第一行是整数n,表示环湖路一共n米长(2<=n<=100)。 第二行是n个整数,每个整数范围[0,10000],按顺时针顺序给出了n个测高点的高度。
输出
最长下坡路段的长度。
样例输入
样例输入1:
5
2 1 5 6 3
样例输入2:
5
2 1 5 4 3
样例输入3:
4
1 1 1 1
样例输出
样例输出1:
3
样例输出2:
4
样例输出3:
0
提示
这是个简单枚举题,枚举起点即可
为了解决这个问题,我们可以使用枚举的方法来找到最长的下坡路段。
我们可以从每个点开始枚举,然后向右遍历环湖路,找到下坡的最大长度。为了方便处理环形结构,我们可以将环湖路的数组复制一份拼接在原数组的后面,以便在遍历时能够正确处理环路。
下面是使用 C 语言编写的解题代码:
#include <stdio.h>
int findLongestDownhill(int heights[], int n) {
int maxDownhill = 0; // 最长下坡长度
int currentDownhill = 0; // 当前下坡长度
// 复制数组并拼接在原数组后面
int extendedHeights[200];
for (int i = 0; i < n; i++) {
extendedHeights[i] = heights[i];
extendedHeights[i + n] = heights[i];
}
// 枚举起点
for (int i = 0; i < n; i++) {
currentDownhill = 0;
int j = i;
// 向右遍历
while (extendedHeights[j] > extendedHeights[j + 1]) {
currentDownhill++;
j++;
// 更新最长下坡长度
if (currentDownhill > maxDownhill) {
maxDownhill = currentDownhill;
}
}
}
return maxDownhill;
}
int main() {
int n;
scanf("%d", &n);
int heights[100];
for (int i = 0; i < n; i++) {
scanf("%d", &heights[i]);
}
int longestDownhill = findLongestDownhill(heights, n);
printf("%d\n", longestDownhill);
return 0;
}
在上述代码中,我们定义了 findLongestDownhill
函数来寻找最长的下坡路段。函数中,我们首先创建一个扩展的高度数组 extendedHeights
,将原高度数组复制一份并拼接在后面,以便在遍历时能够正确处理环路。
然后,我们使用两个循环嵌套来枚举起点和向右遍历。在遍历过程中,我们使用 currentDownhill
变量来记录当前下坡长度,并使用 maxDownhill
变量来记录最长下坡长度。如果当前下坡长度大于最长下坡长度,则更新最长下坡长度。
在 main
函数中,我们首先读取输入的环湖路长度和高度数组。然后,我们调用 findLongestDownhill
函数来找到最长的下坡路段,并将结果输出。
编译并运行上述的代码可以解决该问题。你可以使用 C 语言编译器将代码保存为 .c
文件,然后编译并运行该文件来获取结果。
第4题:吃糖果
现有n(20 > n > 0)个糖果,每天可以吃1个,也可以每天吃2个,也可以每天吃3个,请计算共有多少种不同的吃法。
时间限制:1000
内存限制:65536
输入
输入的每一行包括一组测试数据,即为糖果数n。最后一行为0,表示测试结束。
输出
每一行输出对应一行输入的结果,即为吃法的数目。
样例输入
1
2
3
4
0
样例输出
1
2
4
7
这个问题可以通过动态规划来解决。我们定义一个数组 dp
,其中 dp[i]
表示有 i
个糖果时的吃法总数。
根据题目要求,每天可以吃 1 个、2 个或 3 个糖果。因此,对于 dp[i]
,可以从 dp[i-1]
、dp[i-2]
和 dp[i-3]
中转移得到。具体转移方式如下:
dp[i] = dp[i-1] + dp[i-2] + dp[i-3]
初始条件为 dp[0] = 1
、dp[1] = 1
和 dp[2] = 2
,因为当没有糖果时只有一种吃法,当有一个糖果时也只有一种吃法,当有两个糖果时有两种吃法(可以吃一个糖果两次或者吃两个糖果一次)。
下面是使用 C 语言编写的解题代码:
#include <stdio.h>
int countEatWays(int n) {
int dp[21];
dp[0] = 1;
dp[1] = 1;
dp[2] = 2;
for (int i = 3; i <= n; i++) {
dp[i] = dp[i-1] + dp[i-2] + dp[i-3];
}
return dp[n];
}
int main() {
int n;
while (1) {
scanf("%d", &n);
if (n == 0) {
break;
}
int eatWays = countEatWays(n);
printf("%d\n", eatWays);
}
return 0;
}
在上述代码中,我们定义了 countEatWays
函数来计算给定糖果数目下的吃法总数。我们使用动态规划的思想,从 0 到 n
遍历,计算每个数目下的吃法总数并存储在 dp
数组中。
在 main
函数中,我们使用一个循环来读取输入的糖果数目,并调用 countEatWays
函数来计算吃法总数,并将结果输出。当输入的糖果数目为 0 时,表示测试结束,循环终止。
编译并运行上述的代码可以解决该问题。你可以使用 C 语言编译器将代码保存为 .c
文件,然后编译并运行该文件来获取结果。
第5题:放苹果
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。
时间限制:1000
内存限制:65536
输入
第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。
输出
对输入的每组数据M和N,用一行输出相应的K。
样例输入
1
7 3
样例输出
8
这个问题可以使用递归或动态规划来解决。我们可以定义一个函数 countWays
,用于计算将 M
个苹果放入 N
个盘子中的分法总数。
递归方法:
-
如果
M
或N
的值为 1,表示只有一个盘子或只有一个苹果,那么只有一种分法,即将所有苹果放入一个盘子中。 -
如果
M
小于N
,则将问题转化为将M
个苹果放入M
个盘子中的分法总数,因为有的盘子可能为空。 -
否则,将问题分成两种情况:一种是至少有一个盘子为空,另一种是所有盘子都至少有一个苹果。对于第一种情况,我们可以将问题转化为将
M
个苹果放入N-1
个盘子中的分法总数;对于第二种情况,我们可以将问题转化为将剩余的M-N
个苹果放入N
个盘子中的分法总数。将这两种情况的分法总数相加即可得到结果。
下面是使用 C 语言编写的递归解题代码:
#include <stdio.h>
int countWays(int M, int N) {
if (M == 1 || N == 1) {
return 1;
} else if (M < N) {
return countWays(M, M);
} else {
return countWays(M, N - 1) + countWays(M - N, N);
}
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
int M, N;
scanf("%d %d", &M, &N);
int ways = countWays(M, N);
printf("%d\n", ways);
}
return 0;
}
在上述代码中,我们定义了 countWays
函数来递归计算将 M
个苹果放入 N
个盘子中的分法总数。在函数中,我们首先处理特殊情况,即当 M
或 N
的值为 1 时,返回 1。然后,我们根据问题的性质进行分情况讨论,计算不同情况下的分法总数,并将结果相加返回。
在 main
函数中,我们首先读取测试数据的数目 t
。然后,使用一个循环来读取每组数据的 M
和 N
值,并调用 countWays
函数来计算分法总数,并将结果输出。
编译并运行上述的代码可以解决该问题。你可以使用 C 语言编译器将代码保存为 .c
文件,然后编译并运行该文件来获取结果。