题目:

        一条贪吃的蛇在一个n*m的网格中游走,它只能从一个方格走向另一个相邻的方格,这里相邻的意思是两个方格有公共边。每个方格可以看作是一个房间,其中一些是空的,一些存放有苹果。贪吃的蛇根本不进入空的房间,而进入有苹果的房间后就可以带走所有苹果使房间成为空的。蛇从一个指定的房间出发,最终回到它的家,把一路带来的苹果存储到家中,当然,它希望带来的苹果最多。请编写程序,输入有整数n和m,及n*m的一个矩阵,矩阵元素数值中有一个是 -1,表示蛇的出发位置,有一个是 -2,表示蛇的家的位置,其余数值是非负整数,0表示房间为空,非零整数表示苹果的数目。输出蛇选择的游走路径和获得的最多的苹果数目。

例如输入4*4矩阵:
 7  0  4   18
 4  0  1   1
15 7  11 -1
 0 12 -2  0

则应输出 (2, 3), (1, 3), (0, 3), (0, 2), (1, 2), (2, 2), (2, 1), (3, 1), (3, 2), 带回苹果数为1+18+4+1+11+7+12 = 54。


解析:

对于这题,用到的解法为递归加回朔。我们可以利用一个数组来存储贪吃蛇走过的路径,一个数值来保存从起点开始到当前位置,贪吃蛇收集到的苹果数目;另外用一个数值和一个数组来保存目前所走的所有路径中得到的最大苹果数目及其对应的路径。当当前位置为出口时,将当前这条路径上收集到的苹果数与最大的苹果数尽心比较,若其比目前得到最大的苹果数要大,则更新当前的最大苹果数及其相应的路径。在所有能走的路径均遍历完成之后,即可以得到最终的答案了。

具体细节参考如下代码:

#include <vector>
#include <iostream>
using namespace std;
typedef pair<int, int> Elem;
typedef vector<pair<int, int> > Path;
typedef Path::iterator Iter;
typedef vector<vector<int> > Matrix;
void gridySnake(Matrix& matrix, Path& p, Path& maxP, int i, int j, int m, int n, int& maxApple, int &sum)
{
Elem e(i, j);
if(matrix[i][j] == -2)
{
if(sum > maxApple)
{
maxP = p;    //复制最大苹果数的路径
maxP.push_back(e);
maxApple = sum;
}
return;
}//if
else
{
p.push_back(e);
if(matrix[i][j] != -1) sum += matrix[i][j];
int t = matrix[i][j];
matrix[i][j] = 0;
if(i < m-1 && matrix[i+1][j] != 0)
gridySnake(matrix, p, maxP, i+1, j, m, n, maxApple, sum);
if(i > 0 && matrix[i-1][j] != 0)
gridySnake(matrix, p, maxP, i-1, j, m, n, maxApple, sum);
if(j < n-1 && matrix[i][j+1] != 0)
gridySnake(matrix, p, maxP, i, j+1, m, n, maxApple, sum);
if(j > 0 && matrix[i][j-1] != 0)
gridySnake(matrix, p, maxP, i, j-1, m, n, maxApple, sum);
p.pop_back();
matrix[i][j] = t;
if(matrix[i][j] != -1) sum -= matrix[i][j];
}    //else
}
void printGridySnakePath(Matrix& matrix, int m, int n)
{
if(matrix == NULL || m <= 0 || n <= 0)
{
cout << "Invalid param!\n";
return;
}
int i = 0, j = 0;    //寻找入口
for(; i < m; i++)
{
for(; j < n; j++)
{
if(matrix[i][j] == -1) break;
}
if(j != n) break;
}
if(i == m || j == n)
{
cout << "Can't find entrance!\n";
return;
}
Path p;
Path maxP;
int sum = 0;
int maxApple = INT_MIN;
gridySnake(matrix, p, maxP, i, j, m, n, maxApple, sum);
//输出最佳路径
Iter begin = maxP.begin();
while(begin != maxP.end())
{
cout << "(" << (*begin).first << "," << (*begin).second << ")\n";
begin++;
}//while
cout << "maxApple: " << maxApple << endl;
}
int main()
{
int m, n;
        while(cin >> m >> n && m > 0 && n > 0)
        {
           Matrix matrix(m);
           for(int i = 0; i < m; i++)
           {
               matrix[i].resize[n];
               for(int j = 0; j < n; j++)
               {
                    cin >> matrix[i][j];
               }
            }  
            printGridySnake(matrix, m, n);
        }

getchar();
}