Biggest Number (DFS+剪枝)

描述:
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;
		
	}
}

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每天都想发疯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值