zoukankan      html  css  js  c++  java
  • POJ2411 Mondriaan's Dream 状态压缩+DP

    还记得杭电的“骨牌铺方格”吗,这题可以说是它的强化板了。但是思路是一样的,就是通过得到前面的解来递推后面的结果。
    由于是一个较大的平面,较之杭电那题在行数和列数上都有了较多的组合情况,因此状态压缩有了用武之地。
    这题的一个难点就是如何用0,1来表示摆放的规律,参看别人的想法后,找到的这种方法虽然时间开销相对大了点,但是思路非常好理解。
    对于每一个格子,只有0,1两种状态,0代表没有放置,1代表放置。对于每一行的状态,1的含义会因为上一行的对应项而不同,如果与之对应的上一行的列为0的话,那么这个1代表这里放置了一个竖直的块,如果上一列是1的话那么两行都必须是横着放置的。

    2411 Accepted 328K 1844MS C++ 2143B

    定义了这些后,就是写代码了,本来在judge函数中想通过位运算来解决,但是采用这样的0,1定义对位运算不利,这也是为什么时间开销比较大的原因,在judge时采用了传统的解压方式......逐个判定。

    1. 初始化              
    2. dfs出第一行的状态,注意第一行的1必须要相邻,而且必须是偶数个,能够想清楚吗?
    3. DP更新

    代码如下:

    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <iostream>
    using namespace std;

    int H, W, cnt;
    unsigned int MaxN;
    long long dp[15][1050];

    void print(int x, int L)
    {
    if (x != 0) {
    print(x >> 1, --L);
    printf("%d", x % 2);
    }
    else {
    while (L--)
    printf("0");
    }

    }

    inline int lowbit(int x)
    {
    return x & -x;
    }

    void dfs(int p, int num, int total)
    {
    if (p == W){
    if (!(total & 1)){
    dp[1][num] = 1;
    }
    return;
    }
    else{
    if (total & 1)
    dfs(p+1, num<<1|1, total+1);
    else{
    dfs(p+1, num<<1, total);
    dfs(p+1, num<<1|1, total+1);
    }
    }
    }

    int judge(int x, int y)
    {
    for (int i = 0; i < W; ++i)
    {
    if (x>>i & 1) {// 第i位为奇数
    if (y>>i & 1) {
    if (i == W-1)
    return 0;
    else if (!(x>>(i+1)&1 && y>>(i+1)&1)){
    return 0;
    }
    else ++i;
    }
    }
    else if (!(y>>i & 1)){
    return 0;
    }
    }
    return 1;
    }

    void DP()
    {
    for (int i = 2; i <= H; ++i) { // 针对行的一个遍历
    for (int j = 0; j <= MaxN; ++j) { // 针对状态的一个遍历
    for (int k = 0; k <= MaxN; ++k) { // 针对状态的一个遍历
    if (judge(k, j)) {
    dp[i][j] += dp[i-1][k];
    }
    }
    }
    }
    }

    void init()
    {
    memset(dp, 0, sizeof (dp));
    if (!(H & 1) && !(W & 1)) { // 将状态变小
    if (H < W) {
    H = H + W;
    W = H - W;
    H = H - W;
    }
    }
    else if (!(H & 1)) {
    H = H + W;
    W = H - W;
    H = H - W;
    }
    MaxN = (1<<W)-1; // 所有的可能性
    dfs(0, 0, 0);
    }

    int main()
    {
    while (scanf("%d %d", &H, &W), H|W) {
    if (W & 1 && H & 1) {
    puts("0");
    continue;
    }
    init();
    DP();
    cout << dp[H][MaxN] << endl;
    }
    return 0;
    }


     

  • 相关阅读:
    实例、数据库和表空间(转载)
    异步邮件阻塞MVC请求
    发布Asp.Net MVC 注意事项
    CWebBrowser2 图片缩放,点击小图看大图
    Web服务器与客户端时差问题
    一些好用的eclipse插件
    ASP.NET Deployment and Configuration Problems
    第二届游戏开发者大会
    MVC 请求参数中带有HTML会引发Validation异常 ("A potentially dangerous Request.Form value was detected from the client")
    网络语言标准实施规范 ISO2009
  • 原文地址:https://www.cnblogs.com/Lyush/p/2413160.html
Copyright © 2011-2022 走看看