花生采摘(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原创**

猜你喜欢

转载自blog.csdn.net/c_uizrp_dzjopkl/article/details/82113433