题目:
代码:
#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();
}
程序不能正确运行!!!!