/*
我們要求什麼?
計數。嗯,dp,貌似是個好的辦法。
數目由什麼確定?
不太知道~。
不過我們好像做過相似的題目,比如「開關問題"
鋪的磚受上下左右的磚塊的影響,我們強行只考慮右和下的方向,就和開關問題,這樣有助於簡化一下問題
也就是一塊磚只影響他的右和下的方向鋪磚時候'->'這樣鋪和向下鋪,而不是'<-'這樣鋪和向上鋪。
我們再考慮下乙個稍微簡單的問題,怎樣才能鋪成功呢,在不考慮計數的情況下,由開關問題,我們知道這只和最下邊的那些邊緣是怎樣的有關,
比如當我們把前面的所有的空白都鋪滿了,但是最後有兩個豎直鋪的磚中間只相隔乙個空格的話,我們無論如何都無法鋪成功的。
所以問要維護的是關於邊緣的一些資訊。
比如---+****
***
如上'-』是我們已經鋪好的一部分不考慮了,
'+』是我們正在考慮怎樣鋪的磚,'*'是以後待考慮的
我們維護的就是關於『+』和'*'位置的資訊
'+『有兩種考慮的情況
1.受以前鋪的磚的影響,我們不能在'+'處鋪磚,那麼除了不在'+'處鋪磚外,我們一定要注意'+』處的下面,和右面是不受'+'的影響的
2.如果'+'處可以鋪磚,那麼是橫著鋪,還是豎著鋪?很明顯只要不是最後一排都可以豎著鋪,如果不是最後一列,而且右面那個'*'的地方沒受到上面鋪的磚的影響的話可以
橫著鋪這樣就可以dp了,在乙個位置『0』表示不受以前鋪的磚的影響,'1'表示受到影響。
從上到下,從左到右考慮。
每考慮乙個位的時候考慮怎樣鋪,然後把受影響的位置為1,沒受影響的置為'0'
比如01000,我們考慮到第二位
那麼我們是不能鋪磚的
這樣下面和右面都不受影響
我們把第二位,和第三位置0
為什麼要把第二位置』0『因為在下一排的時候我們在考慮這一列的時候就知道他是否受到了上面的磚的影響了。
其他同理。
最後先開始
010000 和100000這兩個狀態是1,其他都為0 ,代表我們只先考慮了左上角的第乙個位置鋪的磚的情況,
分別代表橫著和豎著
然後在最後
最後那個位為'1'的磚才會被鋪,所以如果那個位為'0'就不計數。
*/#include#include#includeusing namespace std;
typedef unsigned long long ll;
ll dp[2][1 << 20];
int h, w;
ll anss[20][20];
ll func(int n, int m)
if (m == 1)
ll ans = 0;
for (int j = 0; j < (1 << m); j++)
dp[0][j] = 0;
dp[0][1 << (m - 1)] = 1;
dp[0][1 << (m - 2)] = 1;
int temp,know;
know = 0;
for (int j = m - 2; j >= 0; j--)
else
dp[temp][nextt] += dp[know][k];
}} know=temp;
} for (int i =1; i= 0; j--)
temp = know ^ 1;
for (int k = 0; k < (1 << m); k++)
dp[temp][k] = 0;
for (int k = 0; k < (1 << m); k++)
else
if (j&&(!(k&(1<<(j-1)))))}}
know = temp;
} }return ans;
}int main()
} return 0;
}
狀態壓縮DP poj2411 矩形填充木塊問題
從某場筆試遇到的題,群裡太多人改網上 只能對60 我是100 特地記錄下。分析 首先我們定義如下這種填充表示方式 如果乙個骨牌是橫著放的,那麼它所在的兩個方格都填充0.如果它是豎著放的,那麼它所在的兩個格仔中,上面的那個填1,下面的這個填0.如下圖所示 圖來自 部落格 右邊的圖 0 和 1互換就好了...
大樓輪廓線
輸入第一行乙個數表示有n座大樓,後面依次輸入n行,每一行表示大樓的起始點,終點和高度,輸出為大樓輪廓資訊 如下圖 第一行輸出為3 後面有三行輸入表示大樓的資訊 第二行為 1 3 3 第三行為 2 4 4 第三行為 5 6 1 輸出大樓輪廓資訊 第一行 1 2 3 第二行 2 4 4 第三行 5 6 ...
UVa 11270 鋪放骨牌(輪廓線DP)
題意 用1 2骨牌覆蓋n m棋牌,有多少種方法?思路 這道題目是典型的輪廓線dp題。所謂輪廓線dp,就是以整行整列為狀態進行動態規劃時無法進行狀態轉移,那麼此時就可以用到輪廓線,當然,這種方法只能使用在乙個窄棋盤上,大了肯定是不行的,要超時!輪廓線dp就是按照從上到下,從左到右的順序進行狀態轉移,每...