您的位置:首页 > 其它

zoj2563 Long Dominoes(状压dp)

2017-05-03 01:15 295 查看
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1563

Find the number of ways to tile an m*n rectangle with long dominoes – 3*1 rectangles.

Each domino must be completely within the rectangle, dominoes must not overlap (of course, they may touch each other), each point of the rectangle must be covered.

题意:

用1*3得砖铺满整个n*m方格得方法有多少种

tip:

dp[I][s][t]表示到第I行,I行状态为s 上一行为t 这个状态就是这一行的n个铺了还是没谱(0/1)那每个是由谁转移来的呢,,

1.横着放 now 1 1 1 sup 1 1 1是sup111 suup111转移而来

if(col + 3 <= m  ){
if( (tsup & (1 << (col+1)) )&& ( (1 << (col+2)) & tsup) && (tsup & (1 << (col)) )  ){
if( (now & (1 << (col+1)) )&& ( (1 << (col+2)) & now ) && (now & (1 << (col)) ) )
dfs(fl,col+3,suup|(1<<col)|(1<<(col+1))|(1<<(col+2)),sup|(1<<col)|(1<<(col+1))|(1<<(col+2)),now,tsup);
}
```
}


2.竖着放:now=1 sup= 1时候suup 0 sup 0转移来

if( ( ((1<<col)&tsup)) && ( ((1<<col) & now) ) ){
dfs(fl,col+1,suup,sup,now,tsup);
}


3.不放得第一种: now = 0 sup = 1: suup = 1 sup = 1转移来(上面都放好了)

if(!((1<<col)&now) && ((1<<col)&tsup)){
dfs(fl,col+1,suup|(1<<col),sup|((1<<col)),now,tsup);
}


第二种:now = 0 sup = 0: suup = 1 sup = 0转移来 (i+1行会竖着放)

if(!((1<<col)&now)&&(!((1<<col)&tsup)) ){
dfs(fl,col+1,suup|(1<<col),sup,now,tsup);
}


#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
int n,m;
LL dp[2][1024][1024];

void dfs(int fl,int col,int suup,int sup,int now,int tsup){
if(col == m){
//if(sup == (1<<m)-1 && suup == sup && fl == 1) cout <<" asdas "<<dp[(fl-1)%2][sup][suup]<<endl;
dp[fl%2][now][tsup] += dp[(fl-1)%2][sup][suup];
//cout << dp[fl%2][now][tsup]<<endl;
return;
}
//横着放 now 1 1 1是sup111 suup111转移而来
if(col + 3 <= m ){
if( (tsup & (1 << (col+1)) )&& ( (1 << (col+2)) & tsup) && (tsup & (1 << (col)) ) ){
if( (now & (1 << (col+1)) )&& ( (1 << (col+2)) & now ) && (now & (1 << (col)) ) )
dfs(fl,col+3,suup|(1<<col)|(1<<(col+1))|(1<<(col+2)),sup|(1<<col)|(1<<(col+1))|(1<<(col+2)),now,tsup);
}
}

//竖着放:now=1 sup= 1时候suup 0 sup 0转移来
if( ( ((1<<col)&tsup)) && ( ((1<<col) & now) ) ){ dfs(fl,col+1,suup,sup,now,tsup); }

//不放 now = 0 sup = 1: suup = 1 sup = 1转移来
if(!((1<<col)&now) && ((1<<col)&tsup)){ dfs(fl,col+1,suup|(1<<col),sup|((1<<col)),now,tsup); }
//不放 now = 0 sup = 0: suup = 1 sup = 0转移来
if(!((1<<col)&now)&&(!((1<<col)&tsup)) ){ dfs(fl,col+1,suup|(1<<col),sup,now,tsup); }
}

void init(){
for(int s1 = 0 ; s1 < (1<<m) ; s1++)
for(int s2 = 0 ;s2 < (1<<m) ; s2++)
dp[0][s1][s2] = 0;
dp[0][(1<<m)-1][(1<<m)-1] = 1;
for(int i = 1; i <= n; i++){
for(int sup = 0 ; sup < (1<<m) ; sup++){
for(int now = 0 ; now < (1<<m) ; now++){
dfs(i,0,0,0,now,sup);
}
}
for(int s1 = 0 ; s1 < (1<<m) ; s1++)
for(int s2 = 0 ;s2 < (1<<m) ; s2++)
dp[(i+1)%2][s1][s2] = 0;
}
printf("%lld\n",dp[n%2][(1<<m)-1][(1<<m)-1]);
}

int main(){
while(2==scanf("%d%d",&m,&n)){
if(n == 0&& m == 0)
break;
init();
memset(dp,0,sizeof(dp));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: