UVA - 11882Biggest Number dfs+期望剪枝

题意:在一个R行C列(2=<R,C<=15,R*C<=30)的矩阵里有障碍物和数字格(包含1~9的数字)。你可以从任意一个数字格出发,每次沿上下左右的方向走一格,但不能走障碍格中,也不能重复经过,然后把沿途经过的所有数字连起来,问能得到的最大整数是多少?

分析:题目很简单,但容易超时,必须加上预期剪枝,就是当前搜索的和它之后可能搜索的最大长度加起来是否超过当前最优解,如果相等就按字典序比较,否则回溯。

# include<iostream>
# include<cstdio>
# include<cmath>
# include<map>
# include<queue>
# include<string>
# include<string.h>
#include<set>
#include<list>
# include<algorithm>
using namespace std;
char mp[30][30];
int row, col;
int vis[30][30];
int dx[] = { 1,-1,0,0 };
int dy[] = { 0,0,1,-1 };
pair<int, int>que[100];
int head, tail;
int viss[30][30];
string res;
int h(int x,int y) {
	head=tail = 0;
	int cnt = 0;
	que[tail++] = make_pair(x, y);
	memcpy(viss, vis, sizeof(viss));
	while (head < tail) {
		pair<int, int>u = que[head++];
		for (int i = 0; i < 4; i++) {
			int ddx = u.first + dx[i];
			int ddy = u.second + dy[i];
			if (ddx < 0 || ddx >= row || ddy < 0 || ddy >= col)continue;
			if (!viss[ddx][ddy]&&mp[ddx][ddy]!='#') {
				viss[ddx][ddy] = 1;
				cnt++;//还能搜索的长度
				que[tail++] = make_pair(ddx, ddy);
			}
		}
	}
	return cnt;
}
void dfs(int curx,int cury,int layer,string A) {
	int ant = h(curx, cury);
	int l = res.size();
	if (layer + ant < l)return;//期望剪枝
	if (layer + ant == l) {
		if (A + "z" < res)return;//字典序剪枝
	}
	if (A.size() > res.size() || (A.size() == res.size() && res < A))res = A;//更新结果
	for (int i = 0; i < 4; i++) {
		int ddx = curx + dx[i];
		int ddy = cury + dy[i];
		if (ddx < 0 || ddx >= row || ddy < 0 || ddy >= col)continue;
		if (vis[ddx][ddy]||mp[ddx][ddy]=='#')continue;
		vis[ddx][ddy] = 1;
		dfs(ddx, ddy, layer + 1, A+mp[ddx][ddy]);
		vis[ddx][ddy] = 0;
	}

}
int main() {
	while (cin >> row >> col && row&&col) {
		for (int i = 0; i < row; i++)cin >> mp[i];
		memset(vis, 0, sizeof(vis));
		res = "";
		for (int i = 0; i < row; i++) {
			for (int j = 0; j < col; j++) {
				if (mp[i][j]!='#') {
					string A="";
					A+=mp[i][j];
					vis[i][j] = 1;
					dfs(i, j, 1, A);
					vis[i][j] = 0;
				}
			}
		}
		cout << res << endl;
		
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值