描述:
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) and you cannot walk into obstacles or walk into a square more than once. When you finish, you can get a number by writing down the digits you encounter in the same order as you meet them. For example, you can get numbers 9784, 4832145 etc. The biggest number you can get is 791452384, shown in the picture above.
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 characters (without leading or trailing spaces), each of them will be either ‘#’ or one of the nine non-zero digits. There will be at least one non-obstacle squares (i.e. squares with a non-zero digit in it) in the maze. The input is terminated by a test case with R=C=0, you should not process it.
输出:
For each test case, print the biggest number you can find, on a single line.
大意:
给出一个迷宫,从任意非障碍点开始走找到最大的数字,用dfs,但是考虑到最大有25组数据且而且迷宫最多有三十个点,考虑剪枝;
剪枝思路:
当每搜到一个点时,我们求出这个点在图上剩下能够走到的点的总和,用len表示
1.如果
现在的串长 + len < 已存最大串的长度
剪掉
2.如果
现在的串长 + len = 已存最大串的长度
比较两个串的前(现在串长)位,如果现在的串比较小,那么这个串不可能比最大串长,也剪掉;
#include<bits/stdc++.h> using namespace std; typedef unsigned long long ull; typedef long long ll; const ll maxx = 1e18; const int N = 1e6+100; const int p = 1e4; const double eps = 1e-8; int r,c; int dir[4][2]={0,1,0,-1,1,0,-1,0};//方向 string ans;//答案串 char a[16][16]; //存图 bool flag1[16][16];//dfs用 bool flag2[16][16];//serach用 string maxs(string s1,string s2) { if(s1.size()>s2.size()) return s1; if(s1.size()<s2.size()) return s2; if(s1.size()==s2.size()) return max(s1,s2); }//比较两个串的大小 int search(int x,int y)//search表示搜索点能走的点个数 { int sum=1; flag2[x][y]=1;//走过的标记掉 for(int i=0;i<4;i++) { int xx=x+dir[i][0]; int yy=y+dir[i][1]; if(xx<1||yy<1||xx>r||yy>c||flag2[xx][yy]==1||a[xx][yy]=='#') continue; else sum+=search(xx,yy); } return sum; } void dfs(int x,int y,string ss) { ss+=a[x][y]; memcpy(flag2,flag1,sizeof(flag1));//把图复制过来 //memcpy(a,b,sizeof(len));把 b 的 len 个字节复制到 a 里去 int len=search(x,y)-1;//减 1 是去掉本身所占的距离 if(ss.size()+len<ans.size()) return ; if(ss.size()+len==ans.size()) { if(ss<ans.substr(0,ss.size())) return ; } //substr(a,len) ,从第a位开始截取长度为len的字符串 if(len==0) { ans=maxs(ss,ans); return ; }//当没有能走的点时进行比较 flag1[x][y]=1;//进行标记 for(int i=0;i<4;i++) { int xx=x+dir[i][0]; int yy=y+dir[i][1]; if(xx<1||yy<1||xx>r||yy>c||flag1[xx][yy]==1||a[xx][yy]=='#') continue;//保证所有搜的点都是合法点 else dfs(xx,yy,ss); } flag1[x][y]=0;//回溯 return ; } int main() { while(scanf("%d %d",&r,&c)!=EOF) { if(r==0&&c==0) return 0; for(int i=1;i<=r;i++) { for(int j=1;j<=c;j++) { cin>>a[i][j]; } } ans=""; for(int i=1;i<=r;i++) { for(int j=1;j<=c;j++) { if(a[i][j]!='#') { memset(flag1,0,sizeof(flag1)); dfs(i,j,""); } } } cout<<ans<<endl; } }
总结:注意搜索函数里的标记的位置的方法,都是在搜索函数里标记这个点,且所有的搜索点都是合法点,注意这个剪枝的方法,很巧妙。