poj2411 Mondriaan's Dream (状压dp+多米诺骨牌问题)
生活随笔
收集整理的這篇文章主要介紹了
poj2411 Mondriaan's Dream (状压dp+多米诺骨牌问题)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
這道題的解析這個博客寫得很好
https://blog.csdn.net/shiwei408/article/details/8821853
大致意思就是我們可以只處理兩行之間的關系,然后通過這兩個關系推出所有行(有點像矩陣快速冪的思想)
幾個要注意的地方
(1)第0行為全1
(2)發(fā)現自己的思維習慣還是先行在狀態(tài),我自己寫得時候老是寫反。
(3)path的個數可能有很多,不只是1<<n,可以輸入極限數據然后輸出路徑的數目作為數組空間大小
(4)拿小的作列
(5)這道題是人為的設置一種方式,使得二進制與骨牌是一一對應的
如果是橫放,就1 1 如果是豎放就 0 如果不放就是 1
? ? ? ? ? ? ? ? ? ? ? ?? 11 ? ? ? ? ? ? ? ? ? ? ?? 1 ? ? ? ? ? ? ? ? ? ? ?? 0
然后這里的二進制操作非常的秀,要認真學習
#include<cstdio> #include<cstring> #include<algorithm> #define REP(i, a, b) for(int i = (a); i < (b); i++) #define _for(i, a, b) for(int i = (a); i <= (b); i++) using namespace std;typedef long long ll; const int MAXN = 15; ll dp[MAXN][2100]; int path[14000][2], p, n, m;void dfs(int l, int now, int pre) {if(l > m) return;if(l == m){path[p][0] = pre;path[p++][1] = now;return;}dfs(l + 2, (now << 2) | 3, (pre << 2) | 3);dfs(l + 1, (now << 1) | 1, pre << 1);dfs(l + 1, now << 1, (pre << 1) | 1); }int main() {while(~scanf("%d%d", &n, &m) && n){memset(dp, 0, sizeof(dp));if(m > n) swap(n, m);p = 0;dfs(0, 0, 0);dp[0][(1<<m)-1] = 1;_for(i, 1, n)REP(j, 0, p)dp[i][path[j][1]] += dp[i-1][path[j][0]];printf("%lld\n", dp[n][(1<<m)-1]);}return 0; }?
轉載于:https://www.cnblogs.com/sugewud/p/9819323.html
總結
以上是生活随笔為你收集整理的poj2411 Mondriaan's Dream (状压dp+多米诺骨牌问题)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 初入数据科学领域,你需要有七个这样的思维
- 下一篇: 代码质量与规范,那些年你欠下的技术债