Biggest Number (DFS+剪枝)

简介: Biggest Number (DFS+剪枝)

描述:

You have a maze with obstacles and non-zero digits in it:


c04e47b1db01b15487223e02bfd76bf4_cd25c68aadc946378e18b99ebe481ee6.png


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;
  }
}

总结:注意搜索函数里的标记的位置的方法,都是在搜索函数里标记这个点,且所有的搜索点都是合法点,注意这个剪枝的方法,很巧妙。


目录
相关文章
|
6月前
生日蛋糕(dfs剪枝)
生日蛋糕(dfs剪枝)
46 0
DFS之剪枝与优化
DFS之剪枝与优化
77 0
|
3月前
|
算法
DFS算法的实现
DFS算法的实现
61 3
|
5月前
|
算法
DFS算法及应用(一)
DFS(深度优先搜索)是一种图遍历算法,常用于解决穷举问题,如全排列、迷宫问题、图的连通性等。它沿着树的深度分支进行探索,直至达到叶子节点,若无法继续则回溯。例如,将数字6拆分为3个正整数的递增序列问题可以通过DFS实现,类似地,分糖果问题和买瓜问题同样可以用DFS求解。DFS通常涉及递归或栈结构,通过标记已访问节点避免重复。在编程中,会定义递归函数,设定结束条件,然后枚举可能的情况,并处理下一层节点。
|
5月前
|
算法 索引
DFS算法及应用(二)
回溯:回溯就是DFS的一种,在搜索探索过程中寻找问题的解,当发现不满足求解条件时,就回溯返回,尝试其他路径。
Find The Multiple(dfs和bfs都可)
Find The Multiple(dfs和bfs都可)
26 0
|
机器学习/深度学习 测试技术
DFS之剪枝
笔记
80 0
DFS之剪枝
|
vr&ar
DFS之剪枝与优化(二)
AcWing 167. 木棒
140 1
DFS之剪枝与优化(二)