【cofun1370】走道鋪磚問題
Description
有一個專門爲裝修設計方案的設計師。在某一天,他接到了一個項目,爲一棟正在修建的大樓設計走道的地板鋪設方案。此項目的委託人事先便進行了說明:地板磚只有1×2一種規格,而整棟樓中同類走道又有許多個,他不想其中有任何的兩個出現重複的設計方案。因此,設計師必須確定其可行性,即對於一個N×M(N×M爲偶數)的走道,用N×M/2塊1×2的地板磚將其鋪滿,可以有多少種不同的設計方案,如果方案總數少於此類走道的個數,則該項目邊不可能實現。
現在,他需要這樣一個程序:對於輸入的走道規格N、M,計算出可以設計出的不同方案總數(不要求本質不同)。
Input Format
輸入文件僅一行,有兩個數N、M,表示走道的規格。
Output Format
輸出文件也只有一行,即得出的方案總數。
Sample Input
3 4
Sample Output
11
Hint
由於是走道,所以N和M中將會有一個較小。其中min{N,M}≤12,1≤N、M≤40,且N×M爲偶數。
- 分析 :
- min{N, M} <= 12, 因此考慮狀壓DP。
這題不是棋盤問題了,而是覆蓋問題。
但我們可以用類似的思想考慮:
①由於搬磚1 * 2,當前行僅與上一行相關聯。
②dfs出每行的覆蓋情況,把當前行和上一行壓成二進制分別存在數組t,g中。(0:未覆蓋/ 1:已覆蓋)
③枚舉每行進行狀壓DP,轉移方程:
- min{N, M} <= 12, 因此考慮狀壓DP。
f[i][t[j]] = f[i][t[j]] + f[i - 1][g[j]];
f[i][t[j]]:到了第i行,當前行狀態爲t[j]。
注意:由於數據大,需要運用高精度。
【這題的dfs轉移本po理解了好久PUP代碼中有一丟丟註解ヽ( ̄▽ ̄)ノ
- 代碼:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
int n, m, i, j, k, l, p, d, ans, t[50000], g[50000], f[50][5000][75];
void dfs(int q,int x,int y) {
if (q > m) return;
if (q == m) {
d ++;
t[d] = x;
g[d] = y;
return;
}
dfs(q + 1, (x << 1) + 1,y << 1);//豎放
dfs(q + 2, (x << 2) + 3,(y << 2) + 3);//橫放
dfs(q + 1, x << 1, (y << 1) + 1);//不放
return;
}//x:當前行的當前狀態;y:上一行的當前狀態,這裏經過放置後上一行一定要是滿的,po主糊了好久在轉移爲啥不是(y << 1) + 1, (y << 2) + 3, y << 1, 就是因爲不理解y是在放之前的=a=
int main(){
scanf("%d%d", &n, &m);
if (n < m) {i = n; n = m; m = i;}
//讀入
d = 0;
dfs(0, 0, 0);
//搜索出每行和上一行的情況
memset(f, 0, sizeof(f));
f[0][(1 << m) - 1][0] = 1;
f[0][(1 << m) - 1][1] = 1;
//初始化
for(i = 1; i <= n; i ++) {
for(j = 1; j <= d; j ++) {
p = 0;
l = max(f[i][t[j]][0], f[i-1][g[j]][0]);
for(k = 1; k <= l; k ++) {
f[i][t[j]][k] = f[i][t[j]][k]+p+f[i-1][g[j]][k];
p = f[i][t[j]][k]/10;
f[i][t[j]][k] %= 10;
}
f[i][t[j]][0] = l;
while (p > 0) {
f[i][t[j]][0] ++;
f[i][t[j]][f[i][t[j]][0]] = p % 10;
p /= 10;
}
}
}
//狀壓DP
for(i = f[n][(1 << m)-1][0]; i >= 1; i --)
printf("%d",f[n][(1 << m)-1][i]);
//高精度數輸出
}
*另一題是本題的多組數據&答案弱化版,題目大意一致,可以不用高精度,但是沒有保證n,m都是偶數,要一個判斷,一起放在這。→
【cofun1371】 Mondriaan’s Dream
打完上一篇已經道了晚安,可是一想到狀壓題還有好幾道= =趁着清醒再碼一題ORZ
真的睡覺啦~ 晚安:-)