蓝桥杯 格子刷油漆(dp)

 历届试题格子刷油漆  

时间限制:1.0s 内存限制:256.0MB

      

问题描述

  X国的一段古城墙的顶端可以看成2*N个格子组成的矩形(如下图所示),现需要把这些格子刷上保护漆。


  你可以从任意一个格子刷起,刷完一格,可以移动到和它相邻的格子(对角相邻也算数),但不能移动到较远的格子(因为油漆未干不能踩!)
  比如:ad b c e f就是合格的刷漆顺序。
  ce f d a b是另一种合适的方案。
  当已知N时,求总的方案数。当N较大时,结果会迅速增大,请把结果对1000000007(十亿零七)取模。

输入格式

  输入数据为一个正整数(不大于1000

输出格式

  输出数据为一个正整数。

样例输入

2

样例输出

24

样例输入

3

样例输出

96

样例输入

22

样例输出

359635897


思路:较麻烦的dp,要考虑好多情况, 看了一位大神的代码才明白。

//格子刷油漆

#include <stdio.h>

#define MAX_NUM 1000000007

__int64 a[1001] = {0}, b[1001] = {0};  //a[]为从角落的一个格子开始刷的总可能数, b[]为从角落的一个格子开始刷最终回到起始格子的正下方

int main()
{
	int n, i;

	__int64 sum;
	
	scanf("%d", &n);
	
	b[1] = 1;                           //初始化b[1], 显而易见b[1] = 1

	for(i = 2; i <= n; i++)             //因为要回到起点下方, 所以每列格子都有一来一回两个, 除第一列, b[i] = 2*b[i-1]
	{
		b[i] = (b[i-1] * 2) % MAX_NUM;
	}

	a[1] = 1;                          //初始化一下a[1],a[2], 因为递推时要用到(至于a[1,2]怎样得到的,自己数吧)
	a[2] = 6;

	for(i = 3; i <= n; i++)            //a[i]可以由三部分得来,1,i=1时先走起点下方的格子然后的落点有两种(后面就和a[i]一样了)。2,最终回到起点正下方(即b[i])。3,由i-2列辗转的来(如图)
	{
		a[i] = (2 * a[i-1] + b[i] + 4 * a[i-2]) % MAX_NUM;
	}
	
	sum = 4 * a[n];                   //sum是四个角为起点的情况和中间为起点的情况之和
 
	for(i = 2; i <= n-1; i++)         //中间为起点
	{
		sum = (sum + 2*2*a[n-i]*2*b[i-1] + 2*2*a[i-1]*2*b[n-i]) % MAX_NUM;  //中间为起点的情况可分为先向前和先向后两种, 因为必须经过正下方的格子所以必须有一半是b[i-1], 一半是a[i-1]得来
	}
	printf("%I64d\n", sum);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值