1005: Biggest Number解題報告---DFS & BFS & 強剪枝
1005: Biggest Number
時間限制: 1 記憶體限制: 128 MB
題目描述
You have a maze with obstacles and non-zero digits in it:
You can start from any square, walk in the maze, and finally stop at some square. Each step, you may only walk into one of the four neighbouring squares (up, down, left, right)
Your task is to find the biggest number you can get.
輸入
There will be at most 25 test cases. Each test begins with two integers R and C (2<=R,C<=15, R*C<=30), the number of rows and columns of the maze. The next R rows represent the maze. Each line contains exactly C
輸出
For each test case, print the biggest number you can find, on a single line.
樣例輸入
3 7
##9784#
##123##
##45###
0 0
樣例輸出
791452384
參考了CSDN大佬的強剪枝(膜拜.jpg)
BFS來獲取任意點的可達最長路徑,用於剪枝,DFS實現最大值的獲取與更新,本題用string實現字串拼接與大小比較,當然也可用strcmp與strcat函式實現,較麻煩一點。
AC Code:
#include <iostream>
#include<cstdint>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<climits>
#include<map>
#include<queue>
using namespace std;
static const int dir[4][2] = {{1, 0}, {-1, 0}, {0, -1}, {0, 1}};
bool vis[20][20], used[20][20];
int n, m;
char maps[20][20], str[35];
string res, s1, s2;
struct Point{
int x, y;
};
bool is_bound(int x, int y){
return (x >= 0 && x < n && y >= 0 && y < m && maps[x][y] != '#');
}
int path(int x, int y){ //獲取x,y點可達最長路徑
Point p1, p2;
int tail = 0;
p1.x = x, p1.y = y;
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
used[i][j] = vis[i][j];
}
}
queue<Point>q;
q.push(p1);
while(!q.empty()){
p1 = q.front();
q.pop();
for(int i = 0; i < 4; i++){
p2.x = p1.x + dir[i][0];
p2.y = p1.y + dir[i][1];
if(is_bound(p2.x, p2.y) && !used[p2.x][p2.y]){
used[p2.x][p2.y] = true;
str[tail++] = maps[p2.x][p2.y];
q.push(p2);
}
}
}
str[tail] = '\0';
return tail;
}
void dfs(int x, int y, string s){
int len = path(x, y);
if(s.length() > res.length() || (s.length() == res.length() && s > res)){
res = s; //最大值更新
}
if(len + s.length() < res.length()) return; //長度比res小的剪枝
if(len + s.length() == res.length()){ //長度相等,大小可能超過res
sort(str, str + len); //獲取路徑最大值用於剪枝
s2 = s;
for(int i = len - 1; i >= 0; i--){ //s2最大值
s2 += str[i];
}
if(s2 < res) return; //長度相等,字串小的剪枝
}
for(int i = 0; i < 4; i++){
int fx = x + dir[i][0];
int fy = y + dir[i][1];
if(is_bound(fx, fy) && !vis[fx][fy]){
vis[fx][fy] = true;
dfs(fx, fy, s + maps[fx][fy]);
vis[fx][fy] = false; //回溯
}
}
}
int main(){
while(scanf("%d%d", &n, &m) != EOF){
if(n == 0 && m == 0) break;
memset(vis, false, sizeof(vis));
res = "";
for(int i = 0; i < n; i++){
scanf("%s", maps[i]);
}
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
if(maps[i][j] != '#'){
vis[i][j] = true;
s1 = "";
dfs(i, j, s1 + maps[i][j]);
vis[i][j] = false;
}
}
}
// cout<<res<<endl;
printf("%s\n", res.c_str());
}
return 0;
}