poj 2411 (状态压缩dp)

来源:互联网 发布:淘宝数据分析看不懂 编辑:程序博客网 时间:2024/05/01 17:21
//题意:一个n*m的矩形用 1* 2 的卡牌填满 问共有多少种方法//方法:状态压缩+动规的思想 dp[i][j] 表示前i -1行全部填满 第i行状态为j的方法总和//           状态J的二进制状态 0 表示该位被占用了 1 代表 该为是空的//状态转移方程:dp[i][j] = sum(dp[i - 1][k])  (状态j可由状态k推出)//起初有一个地方我有点模棱两可//比如现在第i -1的状态 为 100111  它可以推导出 第i行的状态为 111111//但是并不符合要求//后来仔细想了想 111111 是可以由 100111推出来  但是实际上是由 (100111)的上一个状态推出来的#include <stdio.h>#include <math.h>#include <string.h>#include <algorithm>#include <iostream>using namespace std;long long dp[13][1<<11];long long ans[15][15];int n, m;int isok(int s, int ss);void init(){    int maxn = (1<<m) - 1;    memset(dp, 0, sizeof dp);    for(int i = 0; i <= maxn; i++)  //第一行的各个状态是由dp[0][maxn]推出来的        if(isok(i, maxn))            dp[1][i] += 1;}int isok(int s, int ss){        for(int k = 1; k <= m; )        {            if(s & (1<<(k - 1))) //如果第i行第k列为1            {                if(ss & (1<<(k -1))) //如果第i-1行第k列为1                {                    //必须选择横放                    if( (!(s & (1<<k))) || (!(ss &(1<<k))) || (k == m))  return 0; //如果 第i行第k+1列不为1|| 第i-1行第k+1列不为1 ||k已经在最后一位上 判定状态不合法                    k += 2; // 该位合法 查看两位后                }                else k++; //该位合法 查看下一位            }            else{ //如果第i行第k列为0                if( ! (ss & (1<<(k - 1)))) return 0;  //如果第i - 1行第k列为0  那么状态不合法                k++; // 该位合法 查看下一位            }        }        return 1;}int main(){    while(cin>>n>>m && (n != 0))    {        if( (n&1) && (m&1)) {            cout<<0<<endl;            continue;        }        if(ans[n][m]) {            cout<<ans[n][m]<<endl;            continue;        }        if(n < m)  swap(n, m);   //使m小从而使得状态尽可能少        init();        for(int i = 2; i <= n; i++) //模拟到第i行            for(int j = 0; j < (1<<m); j++)  //模拟第i行状态j                for(int k = 0; k < (1<<m); k++) //模拟第i-1行状态k                    if(isok(j, k)) //如果状态k -> j合法                        dp[i][j] += dp[i - 1][k];        ans[n][m] = ans[m][n] = dp[n][(1<<m) - 1];        cout<<ans[n][m]<<endl;    }    return 0;}


0 0
原创粉丝点击