p1046 [noip2005 普及组] 陶陶摘苹果
时间: 2023-05-31 20:19:23 浏览: 312
NOIP2005第十一届普及组复赛.docx
### 回答1:
题目描述:
陶陶去苹果园摘苹果,这个苹果园很特别,他的苹果树排成了一个矩形网格(如下图)。
其中红色数字代表了对应的苹果数目。陶陶可以沿着网格线爬上爬下去摘苹果,但不能斜着走或越过两棵苹果树之间的空地。陶陶想要摘到尽量多的苹果,他应该怎么摘?
输入输出格式:
输入格式:
输入的第一行有两个整数n,m(1<=n,m<=10)表示苹果园的大小。接下来n行,每行m个整数,用空格隔开,表示每棵树上的苹果数目a(<=a<=100)。
输出格式:
输出一个整数,表示陶陶能摘到的最多的苹果数。
输入输出样例:
输入样例#1:
3 4
1 2 3 4
5
1 3
输出样例#1:
13
输入样例#2:
3 3
1 2 3
5
1 3
输出样例#2:
11
算法1
(暴力枚举) $O(n^2)$
我们可以枚举陶陶的起点,然后从起点开始,每次向右或向下走一步,直到到达右下角。在这个过程中,我们可以记录下经过的苹果数,最后取所有路径中经过的苹果数的最大值即可。
时间复杂度
枚举起点的时间复杂度是 $O(n^2)$,对于每个起点,我们需要走 $O(n)$ 步,因此总时间复杂度是 $O(n^3)$。
C++ 代码
算法2
(动态规划) $O(n^2)$
我们可以用 $f(i,j)$ 表示从 $(1,1)$ 到 $(i,j)$ 的最大苹果数。那么 $f(i,j)$ 可以从 $f(i-1,j)$ 和 $f(i,j-1)$ 转移而来,即:
$$ f(i,j)=\max\{f(i-1,j),f(i,j-1)\}+a(i,j) $$
其中 $a(i,j)$ 表示 $(i,j)$ 这个位置的苹果数。
时间复杂度
我们需要计算 $O(n^2)$ 个状态,每个状态需要 $O(1)$ 的时间计算,因此总时间复杂度是 $O(n^2)$。
C++ 代码
### 回答2:
这道题目是一道经典的搜索题目,需要对搜索算法有所了解才能够解决。
题意概括如下:有一棵苹果树,树上有许多苹果,可以在树上选择一个点作为起点,向下摘苹果,因为树的形状不同,所以每次摘苹果的时候只能摘取横坐标在当前点横坐标之后,且纵坐标比当前点大的苹果。一旦摘了一个苹果之后,这个点就成为了新的起点,并且可以继续向下摘苹果,主人公摘苹果的速度越快,所用时间也越短。请问主人公最短需要多长时间才能摘完所有苹果?
解题思路如下:首先,我们需要先对树进行处理。处理时对每个横坐标按照从小到大的顺序进行排序,如果横坐标相同则按照纵坐标从大到小的顺序进行排序。这样处理之后,如果主人公从一个点出发摘了一个苹果,那么他下一次摘取苹果的起点只能是横坐标在当前点横坐标之后且纵坐标比当前点大的苹果。因为对于同一横坐标的苹果,纵坐标从大到小排列,所以从当前点开始,每个点到达的下一个点都是唯一的,不会有多余的决策。
接下来使用dfs算法进行搜索,搜索的过程中维护当前所在位置和当前时间。每次到达新的点,将时间加上到达该点所需的时间,并将当前位置更新为到达的新点,并进入下一层搜索。当所有的苹果被摘取的时候,将当前时间和历史最短时间进行比较,取最小值。
需要注意的是,在搜索过程中,如果不加任何剪枝,时间复杂度会非常高,甚至无法通过测试。因此需要使用一些剪枝技巧。比如,如果当前时间已经大于历史最短时间,则直接返回,不再进行搜索;对于当前点可以到达的下一层节点,如果剩余的所有苹果的总数已经小于历史最短时间,也可以直接返回。这些剪枝技巧可以大幅降低搜索的时间复杂度。
最终,完成搜索后,输出历史最短时间即可。
### 回答3:
这道题是一道模拟题,需要模拟陶陶摘苹果的过程。首先输入陶陶的身高和苹果树的高度,然后输入每个苹果离地面的高度。我们可以用一个循环来遍历每个苹果的高度,判断这个苹果是否可以被陶陶摘取。如果这个苹果的高度和陶陶的身高之和大于苹果树的高度,那么这个苹果就可以被陶陶摘取。最后,输出陶陶可以摘取的苹果的数量。
具体的实现过程如下:
1. 输入陶陶的身高和苹果树的高度。
2. 定义一个计数变量,记录陶陶可以摘取的苹果数量。
3. 用循环遍历每个苹果的高度:
(1) 输入这个苹果离地面的高度。
(2) 判断这个苹果是否可以被陶陶摘取:如果这个苹果的高度和陶陶的身高之和大于苹果树的高度,那么这个苹果就可以被陶陶摘取。
(3) 如果可以被摘取,就把计数变量加一。
4. 输出陶陶可以摘取的苹果数量。
完整的代码如下:
```
#include <iostream>
using namespace std;
int main() {
int n, m, h; // n: 苹果个数,m: 苹果树的高度,h: 陶陶的身高
int count = 0; // 计数器
cin >> n >> m >> h;
for (int i = 0; i < n; i++) {
int a; // 苹果离地面的高度
cin >> a;
if (h + a >= m) { // 如果苹果可以被摘取
count++;
}
}
cout << count << endl; // 输出陶陶可以摘取的苹果数量
return 0;
}
```
需要注意的地方是,本题的数据规模很小,因此可以使用 int 类型进行计算和存储,不会发生数据溢出的问题。
阅读全文