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;
}

浙公网安备 33010602011771号