格子刷油漆 解题报告

问题描述

  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


思路:这道题是一道动态规划的题目,若要刷2*(n+1)个格子,可以考虑这样六种状态

(以下n,n+1分别表示刷第n,n+1列的墙上的格子,a->b表示刷a列墙上的某个格子后再刷b列墙上的格子,~~~可以为空)

A:~~~->n->(n+1)->(n+1)->n->~~~

B:~~~->n->~~~->n->(n+1)->(n+1)

C:~~~->n->(n+1)->n->(n+1)

D:(n+1)->n->(n+1)->n->~~~

E:(n+1)->n->~~~->n->(n+1)

F:(n+1)->(n+1)->n->~~~

则可推得A[n+1]=2*(A[n]+B[n]+F[n]),B[n+1]=2*(B[n]+C[n]+E[n]),C[n+1]=2*B[n]

     D[n+1]=2*F[n],E[n+1]=2*E[n],F[n+1]=2*(D[n]+E[n]+F[n]) (推导的时候还是要注意对六种形态的理解,然后不要遗漏情况) 

注意n=1的特殊情况,直接输出值为2

n=2时,A[2]=B[2]=C[2]=D[2]=E[2]=F[2]=4

n>=3时,则可利用上值进行递推,注意题目对大值取模,此时数值还是取long类型防止计算过程中发生数值溢出的情况


代码如下:

import java.util.Scanner;

public class Main {
	static int n;
	static long ans, arr1[], arr2[], arr3[], arr4[], arr5[], arr6[];
	static long num = 1000000007;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner reader = new Scanner(System.in);
		n = reader.nextInt();
		if (n == 1)
			System.out.println(2);
		else {
			arr1 = new long[n + 1];
			arr2 = new long[n + 1];
			arr3 = new long[n + 1];
			arr4 = new long[n + 1];
			arr5 = new long[n + 1];
			arr6 = new long[n + 1];
			arr1[2] = 4;
			arr2[2] = 4;
			arr3[2] = 4;
			arr4[2] = 4;
			arr5[2] = 4;
			arr6[2] = 4;
			ans = 0;
			for (int i = 2; i < n; i++) {
				arr1[i + 1] = (2 * (arr1[i] + arr2[i] + arr6[i])) % num;
				arr2[i + 1] = (2 * (arr2[i] + arr3[i] + arr5[i])) % num;
				arr3[i + 1] = (2 * arr2[i]) % num;
				arr4[i + 1] = (2 * arr6[i]) % num;
				arr5[i + 1] = (2 * arr5[i]) % num;
				arr6[i + 1] = (2 * (arr4[i] + arr5[i] + arr6[i])) % num;
			}
			ans = arr1[n] + arr2[n] + arr3[n] + arr4[n] + arr5[n] + arr6[n];
			ans = ans % num;
			System.out.println(ans);
		}
	}

}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值