题目大意:给出一个方格矩阵,矩阵中有数字0~9,任选一个格子为起点,将走过的数字连起来构成一个数,找出最大的那个数,每个格子只能走一次。
题目分析:DFS。剪枝方案:在当前的处境下,找出所有还能到达的点的个数,若当前数字的长度加上个数仍小于目前最优答案的长度,则剪去;若长度相等,则将所有还能到达的数字按从大到小排序后连到当前数字上,如果还比目前最优解小,则减去。找出所有还能到达的点的过程用BFS实现。
代码如下:
# include<iostream> # include<cstdio> # include<queue> # include<string> # include<cstring> # include<algorithm> using namespace std; string ans; int r,c,vis[35][35],mark[35][35],v[1000]; char p[35][35]; int d[4][2]={{-1,0},{1,0},{0,-1},{0,1}}; bool ok(int x,int y) { if(x>=0&&x<r&&y>=0&&y<c) return true; return false; } bool smaller(string a,string b) { if(a.size()<b.size()) return true; if(a.size()==b.size()&&a<b) return true; return false; } int bfs(int x,int y) { queue<int>q; memset(mark,0,sizeof(mark)); q.push(x*c+y); mark[x][y]=1; int res=0; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=0;i<4;++i){ int nx=u/c+d[i][0],ny=(u%c)+d[i][1]; if(ok(nx,ny)&&p[nx][ny]!='#'&&!vis[nx][ny]&&!mark[nx][ny]){ mark[nx][ny]=1; v[res++]=p[nx][ny]-'0'; q.push(nx*c+ny); } } } return res; } void dfs(int x,int y,string ap) { if(smaller(ans,ap)) ans=ap; else{ int len=bfs(x,y); if(ap.size()+len<ans.size()) return ; if(ap.size()+len==ans.size()){ sort(v,v+len); string app=ap; for(int i=len-1;i>=0;--i) app+=char(v[i]+'0'); if(smaller(app,ans)) return ; } } for(int i=0;i<4;++i){ int nx=x+d[i][0],ny=y+d[i][1]; if(ok(nx,ny)&&p[nx][ny]!='#'&&!vis[nx][ny]){ vis[nx][ny]=1; dfs(nx,ny,ap+p[nx][ny]); vis[nx][ny]=0; } } } void solve() { for(int i=0;i<r;++i){ for(int j=0;j<c;++j){ if(p[i][j]!='#'){ memset(vis,0,sizeof(vis)); vis[i][j]=1; string ap=""; ap+=p[i][j]; dfs(i,j,ap); } } } cout<<ans<<endl; } int main() { while(scanf("%d%d",&r,&c)&&r+c) { ans.clear(); for(int i=0;i<r;++i) scanf("%s",p[i]); solve(); } return 0; }