【蓝桥杯官网试题 - 历届试题】格子刷油漆(dp)
題干:
問題描述
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
解題報告:
這是一個雖然可以預處理然后On求解但是比較懶的O(n^2)算法、、、
dp[i]代表以第1列的某一個格子為一個開始,往后涂i列的所有方法數。
dpp[i]代表以第1列的某一個格子為一個開始,先往右涂,的方法數。
對于dpp[i]顯然等于dpp[i-1]*2,因為我可以選擇下一列格子的上面那個或者下面那個。
對于dp[i],顯然可以先向下走,這樣就轉化成dp[i-1]*2的問題了;顯然也可以向右走,這樣就是dpp[i-1]*2的問題了。但是忘了一種情況,可以先往右走一格,再倒退回來一格,再往右走一格,這樣就變成了2*dp[i-2]的情況了,(盜個圖)
也就是說我可以是
1->3->2->4->5....
1->3->2->4->6....
1->4->2->3->5....
1->4->2->3->6....
(不仔細想確實想不到啊。。。)
然后枚舉終點xjb轉移就行了。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define F first #define S second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 2e5 + 5; const ll mod = 1e9 + 7; ll dp[MAX];//從某一列的隨便一個格子開始,下一步往下涂的方案數。 ll dpp[MAX];//下一步往右涂的方案數 int main() {int n;dp[1] = 1; dpp[1] = 1; dp[2] = 6; dpp[2] = 2;for(int i = 3; i<=1000; i++) {dp[i] = ((dp[i-1] + dpp[i-1])*2)%mod + (dp[i-2]*2 * 2)%mod;dp[i] %= mod;dpp[i] = dpp[i-1]*2;dpp[i] %= mod;}while(~scanf("%d",&n)) {ll ans = 0,tmp1,tmp2,tmp;if(n == 1) {printf("2\n");continue;}for(int i = 2; i<=n-1; i++) {tmp1 = ((dpp[i-1]*2)%mod * dp[n-i]*2)%mod;tmp2 = ((dpp[n-i]*2)%mod * dp[i-1]*2)%mod;tmp = tmp1+tmp2;tmp *= 2;ans += tmp%mod;ans %= mod;}ans%=mod;ans += (dp[n]*4)%mod;printf("%lld\n",ans%mod);}return 0 ; }?
總結
以上是生活随笔為你收集整理的【蓝桥杯官网试题 - 历届试题】格子刷油漆(dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【BZOJ - 1001】狼抓兔子(无向
- 下一篇: 【CodeForces - 1199C】