地宫寻宝蓝桥杯,详细讲解。

地宫寻宝 (用了两种解题思考方式,大致相同,看哪种更适合你理解)

解题思路:

题目说了如果遇到比当前最大价值还要大的物品(所以当前最大价值的物品一定要用一个变量来进行记录,方便后续每次的比较),可拿可不拿(所以有两种情况,拿或者不拿);这道题采用递归的方式再好不过了,其实可以把递归的方法理解为能把地图上的每一可能的坐标(每一种可能的情况)都考虑进来然后进行一个比较。下边直接上代码。

#include <iostream>
using namespace  std;
int n,m,k,Count;		//Count用来记录当前满足条件的次数,也是最后输出的值。
int a[1000][1000];			
void dfs(int i, int j, int p, int cnt)		//p代表所有物品中的最大值,cnt代表当前手中的物品数。
{
    
    
	if (i == n - 1 && j == m - 1)		//不管通过怎样的路径,直到走到最右下角才能进行结果的判断。
	{
    
    
		if (cnt == k || cnt == k - 1 && a[i][j] > p)	
            //走到尽头后有两种可能性的判断
            //1:手中的物品数已经道道题目要求的k。
            //2:手中的物品只有k-1,但是最后一个格子的宝藏价值大于目前最大价值p,也满足条件。
			Count++; 
        //return; 这里要不要这句都行,因为下边有强制的边界限制if语句。
	}
	if (i < n)//向下走
	{
    
    
		if (a[i][j] > p)	//向下走有两种情况,即使宝藏比当前最大值还大,可以选择拿或不拿。
			dfs(i + 1, j, a[i][j], cnt + 1);		//这种是拿的情况
		dfs(i + 1, j, p, cnt);	
    //这条语句是不管满不满足条件都不拿的情况,所以这条语句一定不能在if语句内,不能加{};如果加了就变成了只有满足条件的时候才不拿的情况,而忽略了不满足条件的时候。
	}
	if (j < m)//向右走 .  跟上边同理。
	{
    
    
		if (a[i][j] > p)
			dfs(i, j + 1, a[i][j], cnt + 1);
		dfs(i, j + 1, p, cnt);
	}
}
int main()
{
    
    
	cin >> n >> m >> k;
	for (int i = 0; i < n; i++)
	{
    
    
		for (int j = 0; j < m; j++)
		{
    
    
			cin >> a[i][j];
		}
	}
	dfs(0, 0, -1, 0);//这里也要注意一下这里的-1,因为宝藏的价值又可能是0,必须从-1开始,不然地图无法考虑到每一种情况。
	cout << Count;
	system("pause");
	return 0;
}

下边是第二种理解方式,大同小异。

#include <iostream>
using namespace  std;
int n, m, k, Count;
int a[1000][1000];
void dfs(int i, int j, int p, int cnt) p代表所有物品中的最大值,cnt代表当前手中的物品数。
{
    
    
	if (i >= n || j >= m)			//跟上边的判断条件不同,超出边界就return;
		return;
	if (i == n - 1 && j == m - 1)	//一样要走到最右下角才进行判断。
	{
    
    
		if (cnt == k || cnt == k - 1 && a[i][j] > p)
			Count++;
		return;
	}

	if (a[i][j] > p)  //这里跟上边的思想其实是一样的,我们的目的就是为了把地图上的每一种情况都考虑进来,因为是采用的递归的方式,所以一定能够满足每一个坐标情况都能够被考虑。
        //可以这么想,在if语句里的这两句dfs是满足条件下行走。(即是能捡宝藏就捡)
	{
    
    
		dfs(i + 1, j, a[i][j], cnt + 1);
		dfs(i, j + 1, a[i][j], cnt + 1);
	}
    //而这两句dfs是忽略地图上的一切宝物,只管行走
	dfs(i + 1, j, p, cnt);
    dfs(i, j + 1, p, cnt);
    //这四句dfs一定能够遍历出每一种情况。(递归记忆化遍历)
}
int main()
{
    
    
	cin >> n >> m >> k;
	for (int i = 0; i < n; i++)
	{
    
    
		for (int j = 0; j < m; j++)
		{
    
    
			cin >> a[i][j];
		}
	}
	dfs(0, 0, -1, 0);			
	cout << Count;
	system("pause");
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_51721904/article/details/121393683