C语言实现 蓝桥杯 历届试题 格子刷油漆

试题 历届试题 格子刷油漆

                                                                                  蓝桥杯试题解答汇总链接

资源限制

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


问题描述

       X国的一段古城墙的顶端可以看成 2*N个格子组成的矩形(如下图所示),现需要把这些格子刷上保护漆。在这里插入图片描述
你可以从任意一个格子刷起,刷完一格,可以移动到和它相邻的格子(对角相邻也算数),但不能移动到较远的格子(因为油漆未干不能踩!)
  比如:a d b c e f 就是合格的刷漆顺序。
  c e f d a b 是另一种合适的方案。
  当已知 N 时,求总的方案数。当N较大时,结果会迅速增大,请把结果对 1000000007 (十亿零七) 取模。


输入格式

       输入数据为一个正整数N


输出格式

       输出数据为一个正整数。


样例输入

样例一:
2
样例二:
3
样例三:
22

样例输出

样例一:
24
样例二:
96
样例三:
359635897

数据规模与约定

0<N≤1000

试题解析

首先假设我们从某个非顶点格子开始刷要想刷完全部的那么先开始的那一边最终一定要回到他起点的那一列格子,剩下的一部分结束地点可以随意;但如果是顶点开始他只有一侧有格子所以要分成两个大部分讨论:从顶点开始;从非顶点开始;
设dp[i]为给第1~i列格子刷漆且终点与起点不同列的方案数,b[i]为给第1~i列格子刷漆且终点与起点同列的方案
(一)起点为顶点的时候刷漆方案可分为如下几类
①每次刷完一列:
顾名思义就是先刷完一列然后刷下一列。dp[i-1]表示刷完了前i-1列(包含第i-1列)此时工人在第i-1列下面就要给第i列刷漆他可以先刷上面也可以先刷下面,所以这样刷就是dp[i-1]×2种情况。
②每列只刷一个:
这样刷最后的结束点一定和起点在一列。此时工人刷了b[i-1]个漆此时工人在第1列,但其实工人在第i-1列时已经确定了方案所以这里可以假设工人在第i-1列那么刷第i列有两种选择所以b[i]=b[i-1]×2。
③先刷下一列在返回上一列在刷下一列
这样工人刷完在第i-2列,就是4×a[i-2]种因为你是以两列为规律刷所以刷第i-1列2种选择进入第i列有两种选择即乘以4
综上得:dp[i]=2×dp[i-1]+4×dp[i-2]+b[i]
所以顶点
(二)起点为非顶点
①左半部分用b右半部分用dp
②左半部分用dp右半部分用b
使用上面的思路最后就是2×(①+②)
最终结果就是(一)+(二)就是全部的方案种类

代码

#include<stdio.h>
#define mod 1000000007
int main(){
	int i,n;
	scanf("%d",&n);
	if(n==1){// n==1特殊讨论 
		printf("2");
		return 0;
	}
	long long dp[1000],b[1000];// 数据比较大用long long型 
	dp[1]=1,dp[2]=6;// 手算出dp[1]dp[2]b[2]的值 
	b[2]=2;
	for(i=3;i<=n;i++){
		b[i]=(2*b[i-1])%mod;
		dp[i]=(2*dp[i-1]+4*dp[i-2]+b[i])%mod;
	}
	long long sum=4*dp[n]%mod;
	for(i=2;i<n;i++){
		sum=(sum+4*(b[i]*dp[n-i]+b[n-i+1]*dp[i-1]))%mod;
	}
	printf("%I64d",sum);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章