牛客网-青蛙跳迷宫

题目:





代码:

#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<sstream>
#include<fstream>
#include<cstring>
#include<stack>
#include<algorithm>
using namespace std;

class solution{
public:
	void fill_table(vector<vector<int>>&num, vector<vector<int>>&value, int row, int col){
		int temp;
		if (row >= 1 && num[row - 1][col] == 1){//向上
			temp= value[row][col] - 3;
			if (temp > value[row - 1][col]){
				value[row - 1][col] = temp;
				fill_table(num,value,row-1,col);
			}
		}
		if (row +1<row1 && num[row + 1][col] == 1){//向下
			if (value[row][col] > value[row + 1][col]){
				value[row + 1][col] = value[row][col];
				fill_table(num, value, row +1, col);
			}
		}
		if (col+1<col1 && num[row][col+1] == 1){//向右
			temp = value[row][col] - 1;
			if (temp > value[row][col + 1]){
				value[row][col + 1] = temp;
				fill_table(num, value, row, col+1);
			}
		}
		if (col -1>=0 && num[row][col -1] == 1){//向左
			temp = value[row][col] - 1;
			if (temp > value[row][col - 1]){
				value[row][col - 1] = temp;
				fill_table(num, value, row, col-1);
			}
		}
	}
	void search_route(vector<vector<int>>&value, vector<pair<int, int>>&re, int row, int col){
		if (row == 0 && col == 0)return;

		else if (row+1<row1&&value[row][col] + 3 == value[row + 1][col]){//考虑是不是从下方走到该结点的
			re.push_back(make_pair(row + 1, col));
			search_route(value,re,row+1,col);
		}
		else if (row-1>=0&&value[row][col]== value[row-1][col]){//考虑是不是从上方走到该结点的
			re.push_back(make_pair(row -1, col));
			search_route(value, re, row -1, col);
		}
		else if (col - 1>=0&& value[row][col]+1 == value[row][col-1]){//考虑是不是从左边走到该结点的
			re.push_back(make_pair(row, col-1));
			search_route(value, re, row, col-1);
		}
		else{
			if (col + 1 < col1 && value[row][col] + 1 == value[row][col + 1]){//考虑是不是从右边走到该结点的
				re.push_back(make_pair(row, col + 1));
				search_route(value, re, row, col + 1);
			}
		}
	}
	int row1;
	int col1;
};

int main(){
	ifstream fin("C:\\Users\\Dell\\Desktop\\data.txt");
	int row, col, p,temp;
	vector<int>tmp;
	vector<vector<int>>num;
	vector<vector<int>>value;
	vector<pair<int, int>>re;
	solution aa;
	while (fin>>row>>col>>p){
		
		for (int i = 0; i < col; i++)tmp.push_back(0);
		for (int i = 0; i < col; i++)num.push_back(tmp);

		for (int i = 0; i < row; i++){
			for (int j = 0; j < col; j++){
				fin >> temp;
				num[i][j] = temp;
			}	
		}
		value = num;
		for (int i = 0; i < value.size(); i++){
			for (int j = 0; j < value[i].size(); j++){
				value[i][j] = -INT_MIN;
			}
		}
		value[0][0] = p;
		aa.row1 = row;
		aa.col1 = col;
		aa.fill_table(num,value,0,0);//填表
		re.push_back(make_pair(0, col - 1));
		aa.search_route(value,re,0,col-1);
		if (value[0][col - 1] < 0){
			cout << "can not escape!" << endl;
			return 0;
		}
		for (int i = re.size()-1; i >=0;i--){
			cout << "[" << re[i].first << "," << re[i].second << "]";	
			if(i!=0)cout << ",";
		}
	}
	return 0;
}
这种方法相当于利用动态规划思想,此前有道类似的题目在我的博客http://blog.csdn.net/caoyan_12727/article/details/51207826中涉及到的挖管道的问题,只不过这里有

限制条件,限制我们那些地方可以去,那些地方不可以去(即矩阵中的1和0),我们的思想是先填表,然后再逆向搜索路径。这样的做法很耗时间,且多了很多不必要的操作!

优化:

#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<sstream>
#include<fstream>
#include<cstring>
#include<stack>
#include<algorithm>
using namespace std;

class solution{
public:
	void search_route(vector<pair<int, int>>&re,vector<vector<int>>&num, int row, int col, int p){//p代表当前的体力值
		if (row == 0 && col == col1 - 1&&p>=0){
			route.push_back(make_pair(row,col));
			re = route;
			route.pop_back();
		}
		else{
			if (row >= 1 && num[row - 1][col] == 1 && p>= 0){//向上
				route.push_back(make_pair(row, col));
				if(p-3>=0)search_route(re,num, row - 1, col, p - 3);
				route.pop_back();
			}
			if (row + 1<row1 && num[row + 1][col] == 1){//向下
				route.push_back(make_pair(row, col));
				search_route(re,num, row + 1, col, p);
				route.pop_back();
			}
			if (col + 1<col1 && num[row][col + 1] == 1 && p>= 0){//向右
				route.push_back(make_pair(row, col));
				if(p-1>=0)search_route(re,num, row, col + 1, p - 1);
				route.pop_back();
			}
			if (col - 1 >= 0 && num[row][col - 1] == 1 && p>= 0){//向左
				route.push_back(make_pair(row, col));
				if(p-1>=0)search_route(re,num, row, col - 1, p - 1);
				route.pop_back();
			}
		}
	}
	int row1;
	int col1;
	vector<pair<int, int>>route;
};


int main(){
	ifstream fin("C:\\Users\\Dell\\Desktop\\data.txt");
	int row, col, p,temp;
	vector<int>tmp;
	vector<vector<int>>num;
	vector<pair<int, int>>re;
	solution aa;
	while (fin>>row>>col>>p){
		
		for (int i = 0; i < col; i++)tmp.push_back(0);
		for (int i = 0; i < col; i++)num.push_back(tmp);

		for (int i = 0; i < row; i++){
			for (int j = 0; j < col; j++){
				fin >> temp;
				num[i][j] = temp;
			}	
		}
		aa.row1 = row;
		aa.col1 = col;
		re.clear();
		aa.search_route(re,num,0,0,p);//寻路
		if (re.empty() == true)cout << "can not escape!"<< endl;
		else{
			for (int i = 0; i <re.size(); i++){
				cout << "[" << re[i].first << "," << re[i].second << "]";
				if (i != re.size()-1)cout << ",";
			}
		}
	}
	return 0;
}
输出:


这样的解法,相当于树的深度遍历(dfs),我们画一张图来表示青蛙的遍历路径:


可以看到红色圈的是树的深度遍历的根结点,对于每个结点,它有四个可以移动的方向,就相当于一个结点有四个孩子结点(一般的二叉深度搜索中,根结点只有连个孩子

结点),但是由于有四个方向可以移动,所以是一颗四叉树的深度遍历;

另外要注意搜索到每个点的逻辑,如下:

<pre name="code" class="cpp">if (row >= 1 && num[row - 1][col] == 1 && p >= 0){//向上
	route.push_back(make_pair(row, col));
	if (p - 3 >= 0)search_route(re, num, row - 1, col, p - 3);//剪枝操作
	route.pop_back();
}

 也就是说,如果访问到当前结点时,它的体力值如果大于或等于0,那么这个点是可以到达的,所以要将这个点加入到路径中,一旦进行p-3>=0操作,就相当于青蛙在当前结点 

能不能向上走,如果可以则继续递归,如果不可以,则进行剪枝操作;一旦到达(0,col-1)的位置且体力值大于或等于0时,说明存在这样的一条通路,能过脱离迷宫!!!!!!

如果换成:

if (row >= 1 && num[row - 1][col] == 1 && p-3 >= 0){//向上
	route.push_back(make_pair(row, col));
	search_route(re, num, row - 1, col, p - 3);//剪枝操作
	route.pop_back();
}
程序不能正确运行!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值