zoukankan      html  css  js  c++  java
  • UVA11270 Tiling Dominoes —— 插头DP

    题目链接:https://vjudge.net/problem/UVA-11270

     

    题意:

    用2*1的骨牌填满n*m大小的棋盘,问有多少种放置方式。

    题解:

    骨牌类的插头DP。

    1.由于只需要记录轮廓线上m个位置的放置情况(0或1),且m<=10,2^10 = 1024,故可以用二进制对轮廓线的信息进行压缩。

    2.二进制中,第0为代表着当前轮廓线位于第0列的位置的放置情况,以此类推。

    3.具体情况分析,设当前格子为a[i][j]:

    1) 不放置:前提条件为上面的位置a[i-1][j]已经放置了骨牌。原因:如果上面的位置为空,且这次又不放,那么往后就没有机会填补这个空缺了。

    2) 往上放:前提条件为上面的位置a[i-1][j]没有放置骨牌。原因显而易见。

    3) 往左放:前提条件为上面的位置a[i-1][j]放置了骨牌,且左边的位置a[i][j-1]没有放置骨牌。原因:情况1)和情况2)的综合。

    代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <cmath>
     7 #include <queue>
     8 #include <stack>
     9 #include <map>
    10 #include <string>
    11 #include <set>
    12 using namespace std;
    13 typedef long long LL;
    14 const int INF = 2e9;
    15 const LL LNF = 9e18;
    16 const int MOD = 1e9+7;
    17 const int MAXN = 11;
    18 
    19 int n, m, cur;
    20 LL dp[2][1<<MAXN];
    21 
    22 int main()
    23 {
    24     while(scanf("%d%d", &n,&m)!=EOF)
    25     {
    26         if(n<m) swap(n, m);
    27         memset(dp, 0, sizeof(dp));
    28 
    29         cur = 0;
    30         dp[0][(1<<m)-1] = 1;    //初始状态,第一个格子的轮廓线上都有插头,所以就防止了往外放
    31         for(int i = 0; i<n; i++)
    32         for(int j = 0; j<m; j++)
    33         {
    34             cur ^= 1;
    35             memset(dp[cur], 0, sizeof(dp[cur]));
    36             for(int s = 0; s<(1<<m); s++)   //由于有m个插头,而插头的编号从0开始,故最大状态为(1<<m)-1。
    37             {
    38                 //枚举的是上一个格子的所有状态,即当前格子的轮廓线
    39                 int up = 1<<j;  //位于第j列的插头,即上插头
    40                 int left = 1<<(j-1);  //位于第j-1列的插头, 即左插头
    41                 bool hav_up = s&up;
    42                 bool hav_left = s&left;
    43                 if( hav_up )  //不放置,前提是上插头存在
    44                     dp[cur][s^up] += dp[cur^1][s];
    45 
    46                 if( i!=0 && !hav_up)   //往上边放,前提是上插头不存在
    47                     dp[cur][s^up] += dp[cur^1][s];
    48 
    49                 if( j!=0 && hav_up && !hav_left ) //往左边放,前提是上插头存在且左插头不存在
    50                     dp[cur][s^left] += dp[cur^1][s];
    51             }
    52         }
    53 
    54         printf("%lld
    ", dp[cur][(1<<m)-1]);
    55     }
    56 }
    View Code
  • 相关阅读:
    Linux中的文件压缩,打包和备份命令
    Codeforces Round #219 (Div. 2) E. Watching Fireworks is Fun
    [一位菜鸟的COCOS-2D编程之路]COCOS2D中得动作,特效和动画
    软件工程 之 需求分析
    IOS开发之UINavigationController详解
    C++——友元函数和友元类
    拷贝构造函数
    CMake高级用法
    ros-slam的链接
    imu滤波
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/7979048.html
Copyright © 2011-2022 走看看