花生采摘(DFS)
题面*(from luogu)
花生采摘
鲁宾逊先生有一只宠物猴,名叫多多。这天,他们两个正沿着乡间小路散步,突然发现路边的告示牌上贴着一张小小的纸条:“欢迎免费品尝我种的花生!――熊字”。
鲁宾逊先生和多多都很开心,因为花生正是他们的最爱。在告示牌背后,路边真的有一块花生田,花生植株整齐地排列成矩形网格(如图 1 )。有经验的多多一眼就能看出,每棵花生植株下的花生有多少。为了训练多多的算术,鲁宾逊先生说:“你先找出花生最多的植株,去采摘它的花生;然后再找出剩下的植株里花生最多的,去采摘它的花生;依此类推,不过你一定要在我限定的时间内回到路边。”
我们假定多多在每个单位时间内,可以做下列四件事情中的一件:
(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.in
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.out
37
样例2.in
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.out
28
说明
noip2004普及组第2题
题目分析
题目概述:在规定时间内从其中几个有花生的树上采花生(采的时候不算时间),花生树之间的到达需要时间
(题意很好理解,但是用书面上的解释有点难,见谅)
对于此题,我们可以思考一下样例数据的得出——是从(4,2)开始的,而(4,2)上的数是15,是最大的,而后续的规律是 13,9(没有7,时间不够了),能很容易的发现,这是降序的查找方式,找到这个规律,我们就可以比较容易的取解决了
思路:
①找目前最大的;
②边界的确定;
③记录;
代码
#include <bits/stdc++.h>
using namespace std;
int a[25][25],max1,nx,ny,t,nt,n,m,total=0; //a是同map(地图)的作用,max1是存目前最大值(树上的花生数),nx和ny是当前树上花生最大数的坐标位置,nt是去那个位置需要的时间,total是可获得的最多花生数
void search(int x,int y,int k) //x,y是坐标,k是当前还剩多少时间
{
max1=-1; //初始化(要注意,不然一直都是哪个最大的,只会依那一个重复找了)
for (int i = 1; i <= n; i++) //找目前最大的
for (int j = 1; j <= m; j++)
{
if (a[i][j] > max1)
{
max1=a[i][j];
//记录下来坐标
nx = i;
ny = j;
}
}
if (y == 0) y = ny; //适应为0的坐标
nt = abs(nx - x) + abs(ny - y) + nx + 1; //‘abs(nx - x) + abs(ny - y)’这是曼哈顿距离,加上nx是要计算回去的,加1是得要走到这个位置上,而不是这个点
if (k < nt || a[nx][ny] == ,。 0) return; //边界,找不了了(没时间了,走到没有树的地方或地图外了(初始化的都是0))
else
{
total += a[nx][ny]; //加上这个位置的花生数
a[nx][ny] = 0; //打标记,防止重复用一个坐标上的一颗数
search(nx,ny,k-abs(nx-x)-abs(ny-y)-1); //导入目前的坐标,减去本次所用的时间
//不用回溯,因为所用东西都是一次性的
}
}
int main()
{
cin>>n>>m>>t; //输入
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin>>a[i][j];
search(0,0,t); //坐标要从0开始
//x为0是因为在第一次的取时间中它的距离是同路垂直的
cout<<total; //输出
return 0; //完美的结束程序
}
**蒟蒻新星c_uizrp_dzjopkl原创**