X国的一段古城墙的顶端可以看成 2*N个格子组成的矩形(如图所示)
现需要把这些格子刷上保护漆。
你可以从任意一个格子刷起,刷完一格,可以移动到和它相邻的格子(对角相邻也算数),
但不能移动到较远的格子(因为油漆未干不能踩!)
比如:a d b c e f 就是合格的刷漆顺序。
c e f d a b 是另一种合适的方案。
当已知 N 时,求总的方案数。当N较大时,结果会迅速增大,请把结果对 1000000007取模。
输入数据为一个正整数(不大于1000)
输出数据为一个正整数。
例如:
用户输入:
2
程序应该输出:
24
再例如:
用户输入:
3
程序应该输出:
96
再例如:
用户输入:
22
程序应该输出:
359635897
锦囊:
fb(n) 从边缘某格开始,到与它相邻的另一个边缘格子结束
fb(n) = fb(n-1) * 2
fa(n) 从某个边缘格子开始的所有情况
fa(n) = fb(n) + 2*fa(n-1) + 4 * fa(n-2)
最后走相邻边缘格 第1步走相邻边缘格 第2步走相邻边缘格
fk(i,n) 一共有n个格子,从中间的第i个格子为起点,任意结束
fk(i,n) = ( fb(i)*fa(n-i)*2 + fb(n-i+1)*fa(i-1)*2 ) * 2
先走左边再右边 先走右边再左边 有两个可能起点
总情况包含:
从某个边缘格开始的所有情况 4 * fa(i)
从中间某个格子开始的所有情况 i从2到n-1求和:fk(i,n)
因为我看到上面的方法比较难懂,我就直接用暴力的方法了
结果当n为10时得到答案已经比较慢了
而且因为当n较大时,我这个方法是算不出的(可能是超时或溢出),所以就没有取模那一步。
解:
public class Main {
static int sum = 0;
static int n;
static void fun(int[][] a, int num, int x, int y) {
if (num == n * 2) {// 当判定到全部格子刷完时,就算是一种刷法了
sum++;
return;
}
if (x + 1 < 2 && a[x + 1][y] == 0) {// 向下走
a[x + 1][y] = 1;
fun(a, num + 1, x + 1, y);
a[x + 1][y] = 0;
}
if (x - 1 >= 0 && a[x - 1][y] == 0) {// 向上走
a[x - 1][y] = 1;
fun(a, num + 1, x - 1, y);
a[x - 1][y] = 0;
}
if (y + 1 < n && a[x][y + 1] == 0) {// 向右走
a[x][y + 1] = 1;
fun(a, num + 1, x, y + 1);
a[x][y + 1] = 0;
}
if (y - 1 >= 0 && a[x][y - 1] == 0) {// 向左走
a[x][y - 1] = 1;
fun(a, num + 1, x, y - 1);
a[x][y - 1] = 0;
}
if (x + 1 < 2 && y + 1 < n && a[x + 1][y + 1] == 0) {// 向右下走
a[x + 1][y + 1] = 1;
fun(a, num + 1, x + 1, y + 1);
a[x + 1][y + 1] = 0;
}
if (x - 1 >= 0 && y - 1 >= 0 && a[x - 1][y - 1] == 0) {// 向左上走
a[x - 1][y - 1] = 1;
fun(a, num + 1, x - 1, y - 1);
a[x - 1][y - 1] = 0;
}
if (x + 1 < 2 && y - 1 >= 0 && a[x + 1][y - 1] == 0) {// 向左下走
a[x + 1][y - 1] = 1;
fun(a, num + 1, x + 1, y - 1);
a[x + 1][y - 1] = 0;
}
if (x - 1 >= 0 && y + 1 < n && a[x - 1][y + 1] == 0) {// 向右上走
a[x - 1][y + 1] = 1;
fun(a, num + 1, x - 1, y + 1);
a[x - 1][y + 1] = 0;
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
n = in.nextInt();// 格子的列数
// 每个格子都会成为开头的格子
for (int i = 0; i < 2; i++)
for (int j = 0; j < n; j++) {
int[][] a = new int[2][n];// 重置数组
a[i][j] = 1;
fun(a, 1, i, j);
}
System.out.println(sum);
}
}
到时有时间再把正确的做法补上。