蓝桥杯の城墙刷漆(未完)

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);
	}
}
到时有时间再把正确的做法补上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值