小韦老师@NOIP 普及组-2004-花生采摘

2023-10-17 23:40

本文主要是介绍小韦老师@NOIP 普及组-2004-花生采摘,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

小韦老师@NOIP 普及组-2004-花生采摘

题目:

描述

鲁宾逊先生有一只宠物猴,名叫多多。这天,他们两个正沿着乡间小路散步,突然发现路边的告示牌上贴着一张小小的纸条:“欢迎免费品尝我种的花生!――熊字”。

鲁宾逊先生和多多都很开心,因为花生正是他们的最爱。在告示牌背后,路边真的有一块花生田,花生植株整齐地排列成矩形网格(如图1)。有经验的多多一眼就能看出,每棵花生植株下的花生有多少。为了训练多多的算术,鲁宾逊先生说:“你先找出花生最多的植株,去采摘它的花生;然后再找出剩下的植株里花生最多的,去采摘它的花生;依此类推,不过你一定要在我限定的时间内回到路边。”

xxx

我们假定多多在每个单位时间内,可以做下列四件事情中的一件:

  1. 从路边跳到最靠近路边(即第一行)的某棵花生植株;

  2. 从一棵植株跳到前后左右与之相邻的另一棵植株;

  3. 采摘一棵植株下的花生;

  4. 从最靠近路边(即第一行)的某棵花生植株跳回路边。

现在给定一块花生田的大小和花生的分布,请问在限定时间内,多多最多可以采到多少个花生?注意可能只有部分植株下面长有花生,假设这些植株下的花生个数各不相同。

例如在图 2 所示的花生田里,只有位于 (2, 5), (3, 7), (4, 2), (5, 4) 的植株下长有花生,个数分别为 13, 7, 15, 9。沿着图示的路线,多多在 21 个单位时间内,最多可以采到 37 个花生。

输入

第一行包括三个整数,M, N 和 K,用空格隔开;表示花生田的大小为 M × N(1 ≤ M, N ≤ 20),多多采花生的限定时间为 K(0 ≤ K ≤ 1000)个单位时间。接下来的 M 行,每行包括 N 个非负整数,也用空格隔开;第 i + 1 行的第 j 个整数 Pij(0 ≤ Pij ≤ 500) 表示花生田里植株 (i, j) 下花生的数目,0 表示该植株下没有花生。

输出

一个整数,即在限定时间内,多多最多可以采到花生的个数。

输入样例1

6 7 21
0 0 0 0 0 0 0
0 0 0 0 13 0 0
0 0 0 0 0 0 7
0 15 0 0 0 0 0
0 0 0 9 0 0 0
0 0 0 0 0 0 0

输出样例1

37

输入样例2

6 7 20
0 0 0 0 0 0 0
0 0 0 0 13 0 0
0 0 0 0 0 0 7
0 15 0 0 0 0 0
0 0 0 9 0 0 0
0 0 0 0 0 0 0

输出样例2

28

题解:

破题:

根据题目的描述,每走一步用一个时间单位,采摘花生用一个时间单位。 到达每个点需要做以下的事情:

  1. 判断剩下的时间是否能到达下个点,并且到达下个点后,采摘下个点的花生后,剩余的时间还够回到马路上(因为题目要求一定要回到马路上)。
  2. 花费一个时间单位采摘花生,并且将花生数累加到结果中 另外,据题意,一开始在马路上,行数是 0,列数和第一个要去的点(花生数最多的点)相同。
思路:
整体思路:

首先将每个点横坐标、纵坐标和花生数存在一个结构体里,然后组成结构体数组,按照花生数从多到少进行排序。一开始在路边,横坐标是 0,纵坐标是花生数最多的那个点的纵坐标,首先去采摘有花生最多的植株。然后依次去采摘花生次多的植株,直到时间不够。
这里的时间不够理解为:
若时间允许能到达下一个点,但是时间将不允许将下个点的花生采摘后,回到马路上。回到马路上的位置应是行数为 0,列数为出发回马路上的点的列数。
注意采摘花生用一个时间单位完成。

具体步骤:

1.定义:

	// 因为是记录每一个点的信息,行和列最高都是 20,所以最多有 20 ×20 = 400 个点 const int N = 410;  struct peanut {int x;  // 横坐标 int y;  // 纵坐标 int num;  // 点(x, y)的花生数 } pe[N];  // 定义结构体数组,用来存储每个点的信息 int m, n;  // m 行 n 列int k;  // k 个时间单位,要在 k 个时间单位内回到马路上  

2.输入 m,n 和 k。
3.定义一个变量 cnt,作为 pe 数组的下标:

	int cnt = 1;  // 这是 pe 数组的下标,从 1 开始

4.输入花生田,并将每个点的信息存储到 pe 数组中,注意最后 pe 的下标范围是 1~cnt-1

	for (int i = 1; i <= m; i++) {  // 输入 m 行 n 列的花生田 for (int j = 1; j <= n; j++) {pe[cnt].x = i;  // 将横坐标记下 pe[cnt].y = j;  // 将纵坐标记下 cin >> pe[cnt].num;  // 将花生数读入 // 下标加 1,注意最后一次加 1 的时候已经不是 pe 的下标了,// 所以最后 pe 数组的下标范围是 1~cnt-1 cnt++;   }}

5.用 sort 给 pe 数组排序:

	// 用 sort 给 pe 数组排序,下标范围是 1~cnt-1,所以第一个参数是 pe + 1,// 第二个参数是最后一个参加排序的元素的下标加 1,cmp 函数实现排序的规则,见主函数上面 sort(pe + 1, pe + cnt, cmp);

6.定义一个变量 ans,用来存储结果:

	int ans = 0;  // 累加器,用来记录目前采摘的花生数

7.初始化马路出发点的坐标:

	pe[0].x = 0;  // 开始在马路上的横坐标,为 0 // 开始在马路上的纵坐标,为最高花生数的点的纵坐标(准备去采摘花生的第一个点) pe[0].y = pe[1].y;  

8.枚举每个点,若当前点的时间足够,则采摘当前点的花生,并且将所花时间都减掉(从上一个点到当前点的时间,和采摘花生所用的一个时间单位);若时间不足够,则退出循环。

	for (int i = 1; i < cnt; i++) {  // 枚举每个点 if (check(pe[i-1], pe[i])) {  // 用自定义函数判断,若当下这个点时间足够 ans += pe[i].num;  // 则将当下这个点的花生采摘(将花生数累加到累加器中) k--;  // 采摘花生用一个时间单位,所以 k-- } else break;  // 所当下这个点的时间不够,则退出 for 循环 } 

9.输出结果。
10.cmp 函数的实现:

	//  用 sort 给结构体数组 pe 排序的比较函数// 返回值是 bool 型,两个参数都是 peanut 类型的,因为 pe 是 peanut 类型的 bool cmp(peanut a, peanut b) {return a.num > b.num;  // 可以理解成将花生数多的放在前面 }

11.check 函数的实现:

	// 两个参数都是 peanut 型的,参数 a 表示当下所在的点,参数 b 表示即将要去的下一个点 // 函数的功能是判断从 a 点到 b 点是否时间足够,足够则返回 true,否则返回 false bool check(peanut a, peanut b) {  int t = abs(b.x - a.x) + abs(b.y - a.y);  // 算出从 a 点到 b 点要用多少个时间的单位 k -= t;  // 所剩时间减去 t if (k >= b.x + 1) {  // 若所剩时间足够在 b 点采摘花生后回到马路上,记得要加 1 return true;  // 则返回 true } else return false;  // 否则返回 false } 
思考:

1°这道题的贪心体现在什么地方?请说明理由
2°如何对这道题进行分解,能够让我们收获最多?
3°这道题给予我们什么样的思考与收获?

完整代码:
#include <bits/stdc++.h>using namespace std;// 因为是记录每一个点的信息,行和列最高都是 20,所以最多有 20 ×20 = 400 个点 
const int N = 410;  
struct peanut {int x;  // 横坐标 int y;  // 纵坐标 int num;  // 点(x, y)的花生数 
} pe[N];  // 定义结构体数组,用来存储每个点的信息 
int m, n;  // m 行 n 列
int k;  // k 个时间单位,要在 k 个时间单位内回到马路上 //  用 sort 给结构体数组 pe 排序的比较函数
// 返回值是 bool 型,两个参数都是 peanut 类型的,因为 pe 是 peanut 类型的 
bool cmp(peanut a, peanut b) {return a.num > b.num;  // 可以理解成将花生数多的放在前面 
}// 两个参数都是 peanut 型的,参数 a 表示当下所在的点,参数 b 表示即将要去的下一个点 
// 函数的功能是判断从 a 点到 b 点是否时间足够,足够则返回 true,否则返回 false 
bool check(peanut a, peanut b) {  int t = abs(b.x - a.x) + abs(b.y - a.y);  // 算出从 a 点到 b 点要用多少个时间的单位 k -= t;  // 所剩时间减去 t if (k >= b.x + 1) {  // 若所剩时间足够在 b 点采摘花生后回到马路上,记得要加 1 return true;  // 则返回 true } else return false;  // 否则返回 false 
}int main() {cin >> m >> n >> k;  // 输入行数,列数,限制的时间单位数 int cnt = 1;  // 这是 pe 数组的下标,从 1 开始 for (int i = 1; i <= m; i++) {  // 输入 m 行 n 列的花生田 for (int j = 1; j <= n; j++) {pe[cnt].x = i;  // 将横坐标记下 pe[cnt].y = j;  // 将纵坐标记下 cin >> pe[cnt].num;  // 将花生数读入 // 下标加 1,注意最后一次加 1 的时候已经不是 pe 的下标了,所以最后 pe 数组的下标范围是 1~cnt-1 cnt++;   }}// 用 sort 给 pe 数组排序,下标范围是 1~cnt-1,所以第一个参数是 pe + 1,// 第二个参数是最后一个参加排序的元素的下标加 1,cmp 函数实现排序的规则,见主函数上面 sort(pe + 1, pe + cnt, cmp);	int ans = 0;  // 累加器,用来记录目前采摘的花生数 pe[0].x = 0;  // 开始在马路上的横坐标,为 0 pe[0].y = pe[1].y;  // 开始在马路上的纵坐标,为最高花生数的点的纵坐标(准备去采摘花生的第一个点) for (int i = 1; i < cnt; i++) {  // 枚举每个点 if (check(pe[i-1], pe[i])) {  // 用自定义函数判断,若当下这个点时间足够 ans += pe[i].num;  // 则将当下这个点的花生采摘(将花生数累加到累加器中) k--;  // 采摘花生用一个时间单位,所以 k-- } else break;  // 所当下这个点的时间不够,则退出 for 循环 } cout << ans;  // 输出结果 return 0;
}

这篇关于小韦老师@NOIP 普及组-2004-花生采摘的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/228730

相关文章

Regionals 2004 Asia - Beijing Argus 小根堆

点击打开链接 小根堆 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;import java.util.StringTokeni

资料分析系统课-刘文超老师

1、考试大纲 2、解题的问题->解决方法     3、统计术语  基期量与现期量:作为对比参照的时期称为基期,而相对于基期的称为现期。描述具体数值时我们称之为基期量和现期量。 增长量:是指基期量与现期量增长(或减少)的绝对量。增长量是具体值,有单位。增长量=现期量-基期量。增长量有正负,负值代表减少量。增长率:  年均增长量:    年均增长率: 同比和环比

笔试强训,[NOIP2002普及组]过河卒牛客.游游的水果大礼包牛客.买卖股票的最好时机(二)二叉树非递归前序遍历

目录 [NOIP2002普及组]过河卒 牛客.游游的水果大礼包 牛客.买卖股票的最好时机(二) 二叉树非递归前序遍历 [NOIP2002普及组]过河卒 题里面给的提示很有用,那个马的关系,后面就注意,dp需要作为long的类型。 import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息publ

爬取豪ru老师刘艳小说

网址准备 可自行搜索,发现在电脑端无法获取内容,用浏览器仿手机的功能实现 抓包分析,发现网址非常简单,没有任何的反爬措施 可以得到返回的页面,而且字体也没用常见的反爬措施 接下来就分析各个章节的属性就大功告成了 爬取到了 警告,技术不可用于传播黄色

笔记 14 : 彭老师课本第 8 章, UART : 寄存器介绍 ,

(99) 继续介绍 uart 的关于通道的 一整套 寄存器, UCON 等: ++ 接着介绍寄存器 UTRSTAT : ++ 接着介绍读写数据的寄存器: ++ 设置 uart 的波特率,有关的寄存器: ++ (100) (101) 谢谢

信息学奥赛初赛天天练-83-NOIP2014普及组-基础题2-输入设备、输出设备、操作系统、二进制、整数除法、while、do while循环

1 NOIP 2014 普及组 基础题2 4 以下哪一种设备属于输出设备( ) A 扫描仪 B 键盘 C 鼠标 D 打印机 5 下列对操作系统功能的描述最为完整的是( ) A 负责外设与主机之间的信息交换 B 负责诊断机器的故障 C 控制和管理计算机系统的各种硬件和软件资源的使用 D 将没有程序编译成目标程序 11 下列各无符号十进制整数中,能用八位二进制表示的数中最大的是( ) A 296

免费SSL证书大全,加速普及网站实现HTTPS加密

免费SSL证书大全,加速普及网站实现HTTPS加密   SSL 证书用于加密 HTTP 协议,实现网站通过HTTPS加密协议访问。随着国内外各大网站实现全站 HTTPS 协议,以及搜索引擎对使用 HTTPS 协议网站的更加友好,加之互联网对数据和隐私安全的加强,网站添加 SSL 证书并实现 HTTPS 加密协议访问已经成为趋势和必然。 SSL证书大全​zzzjtd.com 而对于给网站添加

沐风老师3DMax地形拟合插件使用方法详解

3DMax地形拟合插件使用教程                       3DMax地形拟合插件,只需单击几下鼠标,即可将地形表面与道路对齐。它很容易使用。 (注意:如果不仔细阅读,会误认为是这是一个道路拟合(投影)到地形的插件,实际上恰恰相反,这是一个地面拟合到道路的插件。)            【适用版本】 3dMax2010及更高版本            【安

【赵渝强老师】大数据生态圈中的组件

大数据体系架构中的组件非常多,每个组件又属于不同的生态圈系统。从最早的Hadoop生态圈体系开始,逐步有了Spark生态圈体系和Flink生态圈体系。因此在学习大数据之前有必要了解一下每一个生态圈体系中具体包含哪些组件,以及它们的作用又是什么。   视频讲解如下: 大数据生态圈中的组件 【赵渝强老师】大数据生态圈中的组件 一、大数据的数据存储组件   在大数据体系中使用了分布式

Scratch教师节:给老师的一封信

小虎鲸Scratch资源站-免费Scratch作品源码,素材,教程分享平台! 【Scratch教师节特别献礼】—— 给老师的一封信:编程之光,照亮梦想之路 在这个金秋送爽、硕果累累的季节里,我们迎来了一个特别而温馨的日子——教师节。在这个充满感激与敬意的时刻,我想用我所学,通过Scratch这一神奇的编程语言,编织成一封特别的信,向所有辛勤耕耘在教育田野上的老师们致以最深的敬意和最真挚的感