http://acm.hust.edu.cn/vjudge/contest/view.action?cid=30851#status//-/0/
题意:给你一个矩阵,矩阵里面有一些数字或者 # 要求在矩阵中走出一条路使得经过的方块组成的数字最大。其中 # 是不能到达的。
思路:Dfs 然后使劲剪枝。这题我用了两个Dfs, 一个用来搜索路径,一个用来剪枝,剪枝就是从某个点开始最多能到达多少个点。
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n, m, len;
int mapn[25][25];
char sta[35], res[35];
bool vis[25][25];
bool visit[25][25];
const int dis[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
int check(int x, int y) //用于剪枝
{
int sum = 1; //计数
for(int i = 0; i < 4; i++){
int nx = x + dis[i][0];
int ny = y + dis[i][1];
if(nx < 0 || nx >= n || ny < 0 || ny >= m ||visit[nx][ny] || !mapn[nx][ny])
continue;
visit[nx][ny] = true;
sum += check(nx, ny);
}
return sum; //返回有多少个点
}
int Dfs(int top, int x, int y) //搜索
{
bool flag = false;
for(int i = 0; i < n; i++){
for(int k = 0; k < m; k++){
visit[i][k] = vis[i][k]; //复制标记数组,用于计数的 check 函数
}
}
int lens = check(x, y) - 1; //计算从 x, y 开始能到达多少个点
if(top + lens < len){
return 0;
}
if(top + lens == len){ //能到达的长度相同
for(int i = 0; i < top; i++){
if(sta[i] < res[i]) //比较搜索过的数字
return 0;
if(sta[i] > res[i])
break;
}
}
for(int i = 0; i < 4; i++){
int nx = x + dis[i][0];
int ny = y + dis[i][1];
if(nx < 0 || nx >= n || ny < 0 || ny >= m ||vis[nx][ny] || !mapn[nx][ny])
continue;
flag = true;
vis[nx][ny] = true;
sta[top] = mapn[nx][ny] + '0';
Dfs(top+1, nx, ny);
vis[nx][ny] = false;
}
if(!flag){ //搜到终点
sta[top] = '\0';
if(len < top){
len = top;
strcpy(res, sta);
}
else if(len == top && strcmp(res, sta) < 0)
strcpy(res, sta);
}
return 0;
}
int main()
{
char str[105];
while(~scanf("%d%d", &n, &m) && (n || m)){
int sx, sy;
for(int i = 0; i < n; i++){
scanf("%s", str);
for(int k = 0; k < m; k++){
if(str[k] == '#')
mapn[i][k] = 0;
else{
mapn[i][k] = str[k] - '0';
}
}
}
len = res[0] = '\0';
for(int i = 0; i < n; i++){
for(int k = 0; k < m; k++){
if(mapn[i][k] != 0){
memset(vis, false, sizeof(vis));
sta[0] = mapn[i][k] + '0';
vis[i][k] = true;
Dfs(1, i, k); //枚举所有的起点
}
}
}
printf("%s\n", res);
}
return 0;
}