• $POJ2411 Mondriaan's Dream$ 状压+轮廓线$dp$


    传送门

    Sol

    首先状压大概是很容易想到的

    一般的做法大概就是枚举每种状态然后判断转移

    但是这里其实可以轮廓线dp

    也就是从上到下,从左到右地放方块

    假设我们现在已经放到了$(i,j)$这个位置

    那么影响这个位置怎么填的其实就只有这个位置上面的位置到它左边的位置这一段的状态

    于是把这一段从上到下从左往右状压起来,1表示被覆盖了,0表示没被覆盖

    $f[i][j][s]$表示填到第$(i,j)$,$(i-1,j)$到$(i,j-1)$的状态为s 的方案数

    转移:

    原则是要把现在考虑的一行的上一行填满,不然它就永远不会被覆盖了

    若$(i-1,j)=0$,即上面的格子没放,这时只能放竖起来的方块

    若$(i-1,j)=1,(i,j-1)=0$即上面的格子放了,左边的格子没放,这时可以放横着的方块

    若$(i-1,j)=1$即上面的格子放了,这时可以不放方块

    最后要注意第一行的状态

    Code

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #define Ri register int
     5 #define ll long long
     6 #define mem(a,b) memset(a,b,sizeof(a))
     7 using namespace std;
     8 int n,m;
     9 ll f[130][1<<11];
    10 int main()
    11 {
    12     while(1)
    13     {
    14         scanf("%d%d",&n,&m);
    15         if(!n||!m)break;
    16         mem(f,0);f[0][(1<<m)-1]=1;
    17         for(Ri i=1;i<=n;i++)
    18             for(Ri j=1,t=m*(i-1)+j;j<=m;j++,t++)
    19                 for(Ri k=0;k<(1<<m);k++)
    20                 if(f[t-1][k])
    21                 {
    22                     ll hhh=f[t-1][k];
    23                     if(i>1 && !(k&1))
    24                         f[t][(k>>1)|(1<<(m-1))]+=hhh;
    25                     if(j>1 && !(k&(1<<(m-1))) && (k&1))
    26                         f[t][(k>>1)|(1<<(m-1))|(1<<(m-2))]+=hhh;
    27                     if(i==1||k&1)
    28                         f[t][k>>1]+=hhh;
    29                 }
    30         printf("%lld
    ",f[n*m][(1<<m)-1]);
    31     }
    32     return 0;
    33 }
    光伴随的阴影
  • 相关阅读:
    使用PowerDesigner 15对现有数据库进行生成图表结构
    dynamic的使用
    js 字符串的replace() 方法和实现replaceAll() 方法
    学习新属性 requestAnimationFrame
    Mapbox 地图样式规范
    Emmet插件使用方法总结
    js循环遍历性能
    lunix部署其前端项目常见报错
    componentWillMount和componentDidMount的区别
    控制浏览器禁止缓存
  • 原文地址:https://www.cnblogs.com/forward777/p/10958581.html
Copyright © 2020-2023  润新知