题意:
给你一个方格图,你在(0,0),最大是(x,y),x是横坐标,y纵坐标,你的基地在(sx,sy),然后你开头是面朝y轴正方向,你每次只能往前走一格,或者右转一格,问你有多少种不同的方法到达基地。
要点:
挺难的,还是看网上的题解。基本思路就是从(sx,sy)将方格图分成4个象限,这样考虑右转几次,同时计算组合,具体的看代码的注释吧。
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MOD = 100000007;
const int maxn = 2005;
ll C[maxn][maxn];
void init()//计算组合数
{
memset(C, 0, sizeof(C));
C[0][0] = 1;
for (int i = 1; i < maxn; i++)
{
C[i][0] = C[i][i]=1;
for (int j = 1; j < i; j++)
{
C[i][j] = (C[i - 1][j - 1] + C[i-1][j])%MOD;
}
}
}
int main()
{
int mini, num, L, R, U, D;
int x, y, sx, sy,t;
init();
scanf("%d", &t);
while (t--)
{
scanf("%d%d%d%d", &x, &y, &sx, &sy);
if (sx == 0 || sy == y)
{
printf("1\n");
continue;
}
L = sx - 1; //注意这里L要-1,因为一开始从(0,0),第0列是不能再取的
R = x - sx;
U = y - sy;
D = sy;
mini = min(min(L, R), min(U, D));//取能够循环转的最大圈数
num = mini * 4;
if (U == mini) num = num;//这里是处理最后一圈的情况
else if (R == mini) num++;//如果最小的是R,那么就可以多走R步,意思就是一圈走完了还能从起点U开始走到R
else if (D == mini) num += 2;
else num += 3;
/*printf("%d %d %d %d\n", U, R, D, L);
printf("%d\n", num);*/
ll ans = 1; //ans一开始就是1,代表走(0,0)->(0,sy)->(sx,sy)这条路
int a[5] = { 0 };
int j = 0;
for (int i = 0; i < num; i++)
{
a[j]++;
ans += C[U][a[0]] * C[R][a[1]] % MOD*C[D][a[2]]%MOD * C[L][a[3]] % MOD;
if (ans >= MOD) ans -= MOD;
j = (j + 1) % 4;//a[j]代表当前的方向
}
printf("%I64d\n", ans);
}
return 0;
}