UVA-11882 Biggest Number (DFS+剪枝)

时间:2021-02-18 22:52:56

题目大意:给出一个方格矩阵,矩阵中有数字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;
}