欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

花生采摘(DFS)

程序员文章站 2022-03-17 20:50:59
...

题面*(from luogu)
花生采摘
鲁宾逊先生有一只宠物猴,名叫多多。这天,他们两个正沿着乡间小路散步,突然发现路边的告示牌上贴着一张小小的纸条:“欢迎免费品尝我种的花生!――熊字”。
鲁宾逊先生和多多都很开心,因为花生正是他们的最爱。在告示牌背后,路边真的有一块花生田,花生植株整齐地排列成矩形网格(如图 1 )。有经验的多多一眼就能看出,每棵花生植株下的花生有多少。为了训练多多的算术,鲁宾逊先生说:“你先找出花生最多的植株,去采摘它的花生;然后再找出剩下的植株里花生最多的,去采摘它的花生;依此类推,不过你一定要在我限定的时间内回到路边。”
花生采摘(DFS)
我们假定多多在每个单位时间内,可以做下列四件事情中的一件:
(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原创**
相关标签: DFS