試題 歷屆試題 格子刷油漆
資源限制
時間限制: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;
}