Luogu7995 solution

Problem

link->https://www.luogu.com.cn/problem/P7995

Solution

看到这题,我的第一反应就是——BFS!然而打完交上去之后发现……TLE!

不过思考过后,可以剪枝优化:当位于 \((x,y)\) 面向 \(w\)(0表示右,1表示下),还剩 \(k\) 步时,则

  • \(x \ne n\)\(y \ne n\)\(k=0\) 时此状态不可以到达终点 \((n,n)\)
  • \(x \ne n\)\(w = 1\)\(k=0\) 时此状态不可以到达终点 \((n,n)\)
  • \(y \ne n\)\(w = 0\)\(k=0\) 时此状态不可以到达终点 \((n,n)\)

那么,就可以打出代码了,最后一个点1.00s闪过

Code

#include<bits/stdc++.h>
using namespace std;
const int N=100;
struct node {
	int x,y,w,turn; //x和y表坐标;w表方向;turn表已转弯几次
};
bool Cango[N][N];
int n,k,T;
bool check(int x,int y) { //此点是否可以到达(存在)
	return(x>=1&&x<=n&&y>=1&&y<=n&&Cango[x][y]);
}
bool ReadBit() { //读入字符串函数
	char c;
	for( ; ; ) {
		c=getchar();
		if(c!=' '&&c!='\n'&&c!='\r')
			return c=='.';
	}
}
int Bfs() { //广搜
	queue<node> Q;
	Q.push(node{1,1,-1,0});
	int ans=0;
	while(!Q.empty()) {
		node t=Q.front(); Q.pop();
		if(t.y!=n&&t.x!=n&&k-t.turn==0) continue; //剪枝
		if(t.y!=n&&t.w==1&&k-t.turn==0) continue;
		if(t.x!=n&&t.w==0&&k-t.turn==0) continue;
		if(t.x==n&&t.y==n) { //方案数+1
			++ans; continue;
		}
		if(t.w==-1) { //最初方向任意
			if(check(t.x,t.y+1)) //向右
				Q.push(node{t.x,t.y+1,0,0});
			if(check(t.x+1,t.y)) //向下
				Q.push(node{t.x+1,t.y,1,0});
		}
		if(t.w==0) { //当前向右
			if(check(t.x,t.y+1)) //继续向右
				Q.push(node{t.x,t.y+1,0,t.turn});
			if(check(t.x+1,t.y)&&t.turn!=k) //改变方向向下
				Q.push(node{t.x+1,t.y,1,t.turn+1});
		}
		if(t.w==1) { //当前向下
			if(check(t.x+1,t.y)) //继续向下
				Q.push(node{t.x+1,t.y,1,t.turn});
			if(check(t.x,t.y+1)&&t.turn!=k) //改变方向向右
				Q.push(node{t.x,t.y+1,0,t.turn+1});
		}
	}
	return ans;
}
int main() {
	scanf("%d",&T);
	while(T--) {
		scanf("%d%d",&n,&k);
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				Cango[i][j]=ReadBit();
		printf("%d\n",Bfs());
	}
	return 1;
}


posted @ 2022-08-02 08:46  lsj2009  阅读(75)  评论(0)    收藏  举报