B. Labyrinth(BFS 记忆化搜索)(双端队列)

记忆化搜索。dp[0] 向左 dp[1] 向右 dp[2] 表示这个点能够满足条件

#include
#include
#include
using namespace std;
char map[2005][2005];
int step[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int vist[2005][2005];
int dp[2005][2005][3];
int n,m;
struct node{
	int x;
	int y;
	int r;
	int l;
};
node star;
int judge(int x,int y,int l,int r){
			if(x>=1&&x<=n&&y>=1&&y<=m&&vist[x][y]){
				if(dp[x][y][0]<l||dp[x][y][1]<r||!dp[x][y][2]){
					dp[x][y][0]=l;
					dp[x][y][1]=r;
					dp[x][y][2]=1;
					return 1;
				}
			}
			return 0;
}
void bfs(){
	memset(dp,0,sizeof(dp));
	queue<node>q;
	 node next;
	 dp[star.x][star.y][0]=star.l;
	 dp[star.x][star.y][1]=star.r;
	 dp[star.x][star.y][2]=1;
	q.push(star);
	while(!q.empty()){
		node cur=q.front();
		q.pop();
		for(int i=0;i<4;i++){
			int x=cur.x+step[i][0];
			int y=cur.y+step[i][1];
			if(map[x][y]=='*')continue;
			//cout<
			int l=cur.l;
			int r=cur.r;
			if(i==1) r--;
			if(i==3) l--;
			if(l<0||r<0) continue;
			if(judge(x,y,l,r)){
				//cout<
				next.x=x;
				next.y=y;
				next.r=r;
				next.l=l;
				q.push(next);
			}
		}
	}
}
int main(){
	cin>>n>>m>>star.x>>star.y>>star.l>>star.r;
	memset(vist,0,sizeof(vist));
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>map[i][j];
			if(map[i][j]=='.')
			vist[i][j]=1;
		}
	}
	int sum=0;
	bfs();
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(dp[i][j][2]==1){
				sum++;
			}
		}
	
	}
	cout<<sum<<endl;
	return 0;
}

看上去很简单,bfs写了一发被fst。。。后来才知道好像一群人都被fst了,这道题好像那些每个点只经过一次的传统bfs都能被叉,只需要构造出一个一块一直上下走,还有一块一直左右走,上下走走到左右走的格子里更优,但已经更新不了,就GG了。后来学习了一下rank1的代码,其实用一个双端队列就可以避免这个问题,每次把上下走的放到队头,左右走的放到队尾。这样的话每次左右遍历时一定是最优的。

#include
#include
#include
#include

using namespace std;
const int MAXN = 2005;

int n,m,stx,sty,X,Y,ans;
bool vis[MAXN][MAXN];
char mp[MAXN][MAXN];
deque<int> Q[5];

void bfs(){
    Q[1].push_front(stx),Q[2].push_front(sty),Q[3].push_front(X),Q[4].push_front(Y);
    while(Q[1].size()){
        int x=Q[1].front(),y=Q[2].front(),l=Q[3].front(),r=Q[4].front();
        Q[1].pop_front();Q[2].pop_front();Q[3].pop_front();Q[4].pop_front();
        if(vis[x][y]) continue;vis[x][y]=1;ans++;
        if(x-1>=1 && mp[x-1][y]!='*')  {
            Q[1].push_front(x-1);Q[2].push_front(y);Q[3].push_front(l);Q[4].push_front(r);          
        }
        if(x+1<=n && mp[x+1][y]!='*'){
            Q[1].push_front(x+1);Q[2].push_front(y);Q[3].push_front(l);Q[4].push_front(r);
        }
        if(y-1>=1 && mp[x][y-1]!='*' && l) {
            Q[1].push_back(x);Q[2].push_back(y-1);Q[3].push_back(l-1);Q[4].push_back(r);
        }
        if(y+1<=m && mp[x][y+1]!='*' && r){
            Q[1].push_back(x);Q[2].push_back(y+1);Q[3].push_back(l);Q[4].push_back(r-1);
        }
    }
}

int main(){
    scanf("%d%d%d%d%d%d",&n,&m,&stx,&sty,&X,&Y);
    for(int i=1;i<=n;i++) scanf("%s",mp[i]+1);
    bfs();cout<<ans;
    return 0;
}

你可能感兴趣的:(codeforces)