zoj2563 Long Dominoes(状压dp)

来源:互联网 发布:linux互斥锁 实现 编辑:程序博客网 时间:2024/05/21 17:09

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));    }}
0 0
原创粉丝点击