奶牛 Bessie 正准备从她最喜爱的草地回到她的牛棚。
农场位于一个 N × N N \times N N×N 的方阵上( 2 ≤ N ≤ 50 2 \leq N \leq 50 2≤N≤50),其中她的草地在左上角,牛棚在右下角。Bessie 想要尽快回家,所以她只会向下或向右走。有些地方有草堆(haybale),Bessie 无法穿过;她必须绕过它们。
Bessie 今天感到有些疲倦,所以她希望改变她的行走方向至多 K K K 次( 1 ≤ K ≤ 3 1 \leq K \leq 3 1≤K≤3)。
Bessie 有多少条不同的从她最爱的草地回到牛棚的路线?如果一条路线中 Bessie 经过了某个方格而另一条路线中没有,则认为这两条路线不同。
搜索+剪枝……
一个十分暴力的搜索是:记录转弯次数 c n t cnt cnt,和目前方向 p o s pos pos,每次搜索是判断方向是否与 p o s pos pos 相同,如果不同则 c n t cnt cnt 要加 1 1 1,但是我们会发现除了样例这个程序其他点都过不了,所以考虑剪枝:
这里给出不用记忆化搜索的代码。
#include <bits/stdc++.h>
#define debug puts("Y")
#define int long long
using namespace std;
const int N = 55;
char c[N][N];
int n, k, cnt;
int dx[] = {0, 1}, dy[] = {1, 0};//0:右 1:下
void dfs(int x, int y, int cir, int pre){
if(c[x][y] == 'H' || cir > k + 1 || (x != n && y != n && cir == k + 1)){//由于第一次搜索时不好处理,所以直接将转弯次数看成k+1即可
return ;
}
if(x == n && y == n){
cnt ++;
return ;
}
for(int i = 0; i < 2; i ++){
int nx = x + dx[i], ny = y + dy[i];
if(i != pre){
dfs(nx, ny, cir + 1, i);
}else{
dfs(nx, ny, cir, i);
}
}
}
void solve(){
cnt = 0;
cin >> n >> k;
memset(c, 'H', sizeof c);//在外面包一圈障碍物,这样就不用判越界了
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= n; j ++){
cin >> c[i][j];
}
}
dfs(1, 1, 0, 114514);
cout << cnt << "\n";
}
signed main(){
int T;
for(cin >> T; T; T --){
solve();
}
return 0;
}
/*
*/