【牛客 - 301哈尔滨理工大学软件与微电子学院第八届程序设计竞赛同步赛(高年级)】小乐乐搭积木(状压dp)
生活随笔
收集整理的這篇文章主要介紹了
【牛客 - 301哈尔滨理工大学软件与微电子学院第八届程序设计竞赛同步赛(高年级)】小乐乐搭积木(状压dp)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題干:
?
小樂樂想要給自己搭建一個積木城堡。
積木城堡我們假設為n*m的平面矩形。
小樂樂現在手里有1*2,2*1兩種地磚。
小樂樂想知道自己有多少種組合方案。
?
輸入描述:
第一行輸入整數n,m。(1<=n,m<=10)輸出描述:
輸出組合方案數。示例1
輸入
復制
2 3輸出
復制
3說明
示例2
輸入
復制
1 3輸出
復制
0示例3
輸入
復制
2 5輸出
復制
8解題報告:
? ?這題狀壓dp,,那種很傳統的方法就不貼了,,今天來貼一個更快的方法、、不同點不在于預處理第一行,而是下面的行,也就是直接找到第二行所有符合的狀態,順便找到對應上一行應該有的狀態,直接做和就可以了。
AC代碼:
/*優化:不去盲目的列舉所有狀態i和j然后判斷狀態j能否到達i,這樣效率很低,因為能到達i的狀態j很少 因此對于每種狀態i,由i區搜索能到達i的狀態j,大大提高效率 有298ms->32ms */ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <queue> #include <algorithm> #include <map> #include <cmath> #include <iomanip> #define INF 0x3f3f3f3f typedef long long LL; using namespace std;const int MAX=(1<<11)+10; int n,m; LL temp[MAX],dp[MAX],biao[15]; bool check(int i){while(i){if(i&1){i>>=1;if(!(i&1))return false;//第j列是1則第j+1列必須是1i>>=1;//繼續判斷下一列}else i>>=1;//繼續判斷下一列}return true; } void Init(){memset(temp,0,sizeof temp);for(int i=0;i<biao[m];++i)if(check(i))temp[i]=1;//初始化第一行 } void dfs(int lie,int now,int cur) {if(lie == m) {dp[now] += temp[cur];return ;}if((now>>lie) & 1) {dfs(lie+1,now,cur);if((now>>(lie+1)) & 1) dfs(lie+2,now,cur|(1<<lie)|(1<<(lie+1)));}else dfs(lie+1,now,cur|(1<<lie)); } void DP(){for(int k=2;k<=n;++k){for(int i=0;i<biao[m];++i) dp[i]=0;for(int i=0;i<biao[m];++i) dfs(0,i,0);for(int i=0;i<biao[m];++i) temp[i]=dp[i];} }int main(){biao[0]=1;for(int i=1;i<12;++i)biao[i]=2*biao[i-1];scanf("%d%d",&n,&m);//if(n<m)swap(n,m);//始終保持m<n,提高效率Init();DP();printf("%lld\n",temp[biao[m]-1]);//輸出最后一行到達時的狀態必須全部是1return 0; }?
總結
以上是生活随笔為你收集整理的【牛客 - 301哈尔滨理工大学软件与微电子学院第八届程序设计竞赛同步赛(高年级)】小乐乐搭积木(状压dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【HDU - 4217 】Data St
- 下一篇: 储蓄国债怎么买?从哪里可以查看储蓄国债的