蓝桥杯2013年第四届真题-格子刷油漆

在这里插入图片描述
在这里插入图片描述
思路:
对于题目给出的几个行走规则,走的方式有很多;但是以某个格子为出发点的方式固定。

将整个矩形刷完,我们的起点主要分为以下两大类:
1.从四个顶点之一出发
2.从中间某个点出发

1.从四个顶点之一出发

①第一步走同一列的另一个格子,然后再走下一列。接着重复这个过程。如下图所示:
在这里插入图片描述
假设从顶点A出发,那么第一步没得选,只能走向B;接着在B点时,此时就有两种选择方案,要么走向C,要么走向D。假设走向了D,那么此时D点就只能选C,接着在C点时,其又可以选择E或F……然后重复上面这个过程,直到最终走到矩形的另一侧

这种情况下,我们用a[i] 来表示一个2x i 的 矩形 从一个顶点出发,要按规则走完全部格数的方案数。

a[i]=a[i-1]*2;

②第一步走下一列,之后也还是不断地走下一列,当最终走到最后一列后再返回。返回时,由于格子的高度为2,那么在返回时,路径唯一,如下图所示:
在这里插入图片描述
假设从顶点A出发,那么第一步可以选C或D共两种方案,假设选的是C,那么接下来又可以选择E或F……当最后到了最后一列,比如到了I,那么此时返回的路线也就唯一确定了
我们用b[i] 表示从一个顶点 出发最后到达他的相对位置的方案种数为多少

于是得到状态转移方程:b[ i ]=2×b[ i-1] (乘2的原因是每次都有两种选择,如在A点可选C或D)

③第一步走另一列,再由该列返回前一列,然后再从前一列走向另一列的另一个格子,如下图所示

在这里插入图片描述
在这里插入图片描述
假设从顶点A出发,那么其有两条路线:A->C->B->D或A->D->B->C,假设到了点D,则D又可以有两种选择(要么到E要么到F),此时又可再重复在点A的行为,直到最终到达矩形的另一侧
显然这也属于“一趟过去,不再返回”的类型,因此也用数组a来表示,则可以把问题规模转换成a[ i-2 ]
于是得到状态转移方程:a[ i ] = 2 × 2 × a[ i-2 ] (第一个乘2是选C或D,二个乘2是选E或F)

2.从中间出发

在这里插入图片描述
我们从图中i=3(E点)处出发(以i为分割线,将图分为左边的ABCDEF以及右边的GHIJ),为了遍历所有格子,我们需要先走完左边的这个整体(特别注意:这里必须倒回到F才能继续走右边),然后再把右边视为以G或者H为起点的一组格子将其走完(因此这里需要乘以2,两种起点出发嘛)
分析上述的流程,可以得到从中间出发的方案数为:( b[ i ] ) × ( 2 × a[ n-i ] )
同理,我们可以先走右边的EFGHIJ,然后再走左边的ABCD
这样的方案数为:(b[ n-i+1]) × (2×a[ i - 1])
由于上面的所有起始点都是以E为出发点行走的,我们同理也可以以F为起点出发,那么从第i列开始刷漆的方法就有:[ (b[ i ])×(2×a[ n-i ])+(b[ n-i+1])×(2×a[ i - 1]) ]×2

用动态规划法,

package com.lanqiao2013;

import java.util.Scanner;

public class GeZiShuayouqiDemo {
	static final long MOD=1000000007;
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int n = 0;
		n= scanner.nextInt();
		scanner.close();
		
		if(n==1) { 
			System.out.println(2);
			return;
		}	
		
		long[] a = new long[1005];
		long[] b = new long[1005];

		// base case
		a[1] = 1;
		a[2] = 6;
		b[1] = 1;
		b[2] = 2;

		// 从四个角开始
		for (int i = 3; i <= n; i++) {
			b[i] = (2 * b[i - 1])%MOD;
			a[i] = (2 * a[i - 1] + b[i] + 2 * 2 * a[i - 2])%MOD;
		}
		long sum = 4 * a[n]%MOD;

		// 从中间开始
		for (int i = 2; i < n; i++) {
			sum = (sum + ((b[i]) * (2 *a[n - i]) + (b[n - i + 1]) * (2 * a[i - 1])) * 2)%MOD;
		}
		System.out.println(sum);
	}

}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值