hdu 5335 Walk Out bfs 2015 Multi-University Training Contest 4 09

题意:从(1,1)走到(n,m)时经过的01串二进制的值最小。

首先确定从(1,1)走到矩阵中的任意一格(i,j),需要走i+j-2步,那么尽可能的走0且尽早的走0肯定是最优的。因此对于每个相同步数x,可以确定的是走x步能过走到的点,考虑到影响结果的走法 :x步的走下一个x+1步的结果,要么是0,要么是1.那么如果有0的话肯定选0,这种走法,那就将其加进队列,否则若在x+1步走一个0都没遇到,就将所以的x+1的走法加进队列进行迭代即可。确定了走的方法,再来看起点,很明显,只要从(1,1)这个点bfs到里终点最近的点,也就是离(1,1)最远的点(即i+j尽可能大)即可。

下附几组测试数据

#include <bits/stdc++.h>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cmath>
#include <time.h>
#include <vector>
#include <cstdio>
#include <string>
#include <iomanip>
///cout << fixed << setprecision(13) << (double) x << endl;
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define ls rt << 1
#define rs rt << 1 | 1
#define pi acos(-1.0)
#define eps 1e-8
#define Mp(a, b) make_pair(a, b)
#define asd puts("asdasdasdasdasdf");
typedef long long ll;
//typedef __int64 LL;
const int inf = 0x3f3f3f3f;
const int N = 1010;

int n, m;
struct node{
	int x, y;
	bool operator < ( const node &rhs ) const {
		if( x != rhs.x )
			return y < rhs.y;
		return x < rhs.x;
	}
};

char c[N][N];
queue <node> q;
vector <node> v;
string ans;
bool vis[N][N];
int dir[4][2] = {
	1, 0, -1, 0, 0, 1, 0, -1
};

int main()
{
	int tot;
	scanf("%d", &tot);
	while( tot-- ) {
		scanf("%d%d", &n, &m);
		for( int i = 1; i <= n; ++i )
			scanf("%s", c[i]+1);
		if( n == m && n == 1 && c[1][1] == '1' ) {
			puts("1");
			continue;
		}
		memset( vis, 0, sizeof( vis ) );
		bool inq = 0;
		while( !q.empty() )	q.pop();
		node tmp;
		tmp.x = tmp.y = 1;
		if( c[1][1] == '0' ) {
			q.push(tmp);
			vis[1][1] = 1;
			inq = 1;
		}
		while( !q.empty() ) {
			node now = q.front();
			q.pop();
			for( int i = 0; i < 4; ++i ) {
				int x = now.x + dir[i][0];
				int y = now.y + dir[i][1];
				if( x > n || x == 0 || y > m || y == 0 )
					continue;
				if( vis[x][y] || c[x][y] == '1' )
					continue;
				vis[x][y] = 1;
				node nxt;
				nxt.x = x, nxt.y = y;
				q.push( nxt );
				if( x+y >= tmp.x+tmp.y ) {
					tmp.x = x;
					tmp.y = y;
				}
			}
			if( tmp.x >= n && tmp.y >= m )
				break;
		}
		if( tmp.x >= n && tmp.y >= m ) {
			printf("0\n");
			continue;
		}
		ans = "";
		for( int i = 1; i <= n; ++i ) {
			for( int j = 1; j <= m; ++j ) {
				if( vis[i][j] && i+j == tmp.x + tmp.y ) {
					node u;
					u.x = i, u.y = j;
					q.push( u );
				}
			}
		}
		if( !inq ) {
			q.push( tmp );
			ans += '1';
			vis[1][1] = 1;
		}
		v.clear();
		while( 1 ) {
			bool OK = 0;	//下一个是否出现0
			while( !q.empty() ) {
				node now = q.front();
				q.pop();
				node n1, n2;
				n1.x = n2.x = now.x;
				n1.y = n2.y = now.y;
				n1.x++, n2.y++;
				if( n1.x >= 1 && n1.x <= n && n1.y >= 1 && n1.y <= m ) {
					if( !OK ) {
						if( !vis[n1.x][n1.y] ) {
							if( c[n1.x][n1.y] == '0' ) {
								OK = 1;
								v.clear();
								v.push_back( n1 );
							}
							else 
								v.push_back( n1 );
							vis[n1.x][n1.y] = 1;
						}
					}
					else {
						if( !vis[n1.x][n1.y] && c[n1.x][n1.y] == '0' ) {
							v.push_back( n1 );
							vis[n1.x][n1.y] = 1;
						}
					}
				}
				if( n2.x >= 1 && n2.x <= n && n2.y >= 1 && n2.y <= m ) {
					if( !OK ) {
						if( !vis[n2.x][n2.y] ) {
							if( c[n2.x][n2.y] == '0' ) {
								OK = 1;
								v.clear();
								v.push_back( n2 );
							}
							else
								v.push_back( n2 );
							vis[n2.x][n2.y] = 1;
						}
					}
					else {
						if( !vis[n2.x][n2.y] && c[n2.x][n2.y] == '0' ) {
							v.push_back( n2 );
							vis[n2.x][n2.y] = 1;
						}
					}
				}
			}
			int sz = v.size();
			for( int i = 0; i < sz; ++i )
				q.push( v[i] );
			if( q.empty() )	break;
			if( OK )
				ans += '0';
			else
				ans += '1';
			v.clear();
		}
		cout << ans << endl;
	}
	return 0;
}
/*
5 5
11101
00100
01000
01011
11111
5 5
00011
11101
11011
11111
11101
5 5
00011
11011
00011
01011
11011
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值