题目大意见紫书218。
一看到这道题第一反应就是dfs,然后第二反应就是单纯的dfs会T。。于是就考虑迭代加深。
首先预处理, 找到每个连通块的大小以及编号, maxd为当前寻找的数的位数,从1开始到最大连通块大小,于是对于障碍物 或者所在连通块大小小于maxd的数字格就不需要枚举了, 另外已经得到的数字如果已经小于的当前ans, 就直接return不需要继续找。
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <sstream>
#include <set>
#include <vector>
#include <stack>
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1e6 + 10;
const double eps = 1e-9;
int n, m, maxd, cnt;
string ans;
char mp[20][20];
int vis[20][20], nvis[20][20];
int dir[4][2] = {0,1, 1,0, 0,-1, -1,0};
int flag;
struct pnt{
int x, y;
int val;
bool operator < (const pnt &ths) const {
return val > ths.val;
}
}a[50];
bool check(int x, int y) {
if(x < 0 || x >= n || y < 0 || y >= m || mp[x][y] == '#') return false;
return true;
}
void block(int x, int y) {
nvis[x][y] = 1;
cnt++;
for(int i = 0; i < 4; i++) {
int nx = x + dir[i][0];
int ny = y + dir[i][1];
if(check(nx, ny) && !nvis[nx][ny]) {
block(nx, ny);
}
}
}
bool dfs(int step, int x, int y, string s) {
if(step == maxd) {
flag = 1;
if(s.size() > ans.size()) {
ans = s;
}
else if(s.size() == ans.size()) {
ans = max(ans, s);
}
return true;
}
int ok = 0;
for(int i = 0; i < 4; i++) {
int nx = x + dir[i][0];
int ny = y + dir[i][1];
if(check(nx, ny) && !vis[nx][ny]) {
memcpy(nvis, vis, sizeof vis);
cnt = 0;
block(nx, ny);
if(maxd - 1 - step >= cnt) {
ok = 0;
continue;
}
if(flag) {
string s1, s2;
int len = ans.size();
for(int i = 0; i < min(len, step+1); i++) {
s1 += ans[i];
s2 += s[i];
}
if(s1 > s2) continue;
}
vis[nx][ny] = 1;
if(dfs(step+1, nx, ny, s + mp[nx][ny])) ok = 1;
vis[nx][ny] = 0;
}
}
return ok;
}
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
while(scanf("%d%d", &n, &m) != EOF && n && m) {
CLR(mp); CLR(nvis);
int num = 0;
for(int i = 0; i < n; i++)
scanf("%s", mp[i]);
maxd = 0; ans.clear();
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
if(!vis[i][j] && mp[i][j] != '#') {
cnt = 0;
block(i, j);
maxd = max(maxd, cnt);
}
if(mp[i][j] != '#') {
a[num].val = mp[i][j] - '0';
a[num].x = i;
a[num++].y = j;
}
}
}
flag = 0;
sort(a, a + num);
for(; maxd >= 0 && !flag; maxd--) {
for(int k = 0; k < num; k++) {
CLR(vis);
int i = a[k].x, j = a[k].y;
string x;
x += mp[i][j];
vis[i][j] = 1;
if(dfs(0, i, j, x))
flag = 1;
}
}
cout << ans << endl;
}
return 0;
}