【USACO2021 Walking Home 】题解

题目

Bessie the cow is trying to walk from her favorite pasture back to her barn.

The pasture and farm are on an N×N
grid (2≤N≤50

), with her pasture in the top-left corner and the barn in the bottom-right corner. Bessie wants to get home as soon as possible, so she will only walk down and to the right. There are haybales in some locations that Bessie cannot walk through; she must walk around them.

Bessie is feeling a little tired today, so she wants to change the direction she walks at most K
times (1≤K≤3

) .

How many distinct paths can Bessie walk from her favorite pasture to the barn? Two paths are distinct if Bessie walks in a square in one path but not in the other

奶牛 Bessie 正准备从她最喜爱的草地回到她的牛棚。

农场位于一个 N×N
的方阵上(2≤N≤50

),其中她的草地在左上角,牛棚在右下角。Bessie 想要尽快回家,所以她只会向下或向右走。有些地方有草堆(haybale),Bessie 无法穿过;她必须绕过它们。

Bessie 今天感到有些疲倦,所以她希望改变她的行走方向至多 K
次(1≤K≤3

)。

Bessie 有多少条不同的从她最爱的草地回到牛棚的路线?如果一条路线中 Bessie 经过了某个方格而另一条路线中没有,则认为这两条路线不同。

思路

\(dp(x, y, k, 0/1)\) 代表此时在格子 \((x,y)\),已转弯 \(k\) 次,现在朝着方向下/右(\(0/1\))的方案数。

然后就可以从左边和上边转移过来,转移的时候需要考虑是否转弯。

总结

对于棋盘上年统计方案的题目,如果棋盘不是很大,可以考虑dp,把限制条件写入转态即可。

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n, m, i, j, k, t, kx, p; 
int dp[55][55][5][2], ans; 
char s[55][55]; 

signed main()
{
	scanf("%lld", &t); 
	while(t--)
	{
		memset(dp, 0, sizeof(dp)); ans=0; 
		scanf("%lld%lld", &n, &k); 
		for(i=1; i<=n; ++i) scanf("%s", s[i]+1); 
		if(s[1][1]=='H'){ printf("0\n"); continue; }
		dp[1][1][0][0]=dp[1][1][0][1]=1; 
		for(i=1; i<=n; ++i)
			for(j=1; j<=n; ++j)
				if(s[i][j]=='.')
					for(kx=0; kx<=k; ++kx)
					{
						dp[i][j][kx][0]+=dp[i-1][j][kx][0]; 
						if(kx) dp[i][j][kx][0]+=dp[i][j-1][kx-1][1]; 
						dp[i][j][kx][1]+=dp[i][j-1][kx][1]; 
						if(kx) dp[i][j][kx][1]+=dp[i-1][j][kx-1][0]; 
					}
		for(kx=0; kx<=k; ++kx)
			ans+=(dp[n-1][n][kx][0]+dp[n][n-1][kx][1]); 
		printf("%lld\n", ans); 
	}
	return 0;
}
posted @ 2021-12-21 17:51  zhangtingxi  阅读(607)  评论(2编辑  收藏  举报