• P1879 [USACO06NOV]玉米田Corn Fields[轮廓线DP]


    状压暴力显然可做。但是数据出的再大一点就要稳T了。理论$O(n4^m)$,只不过实际跑不满。

    考虑用轮廓线DP,设$f(i,j,S)$为处理到$(i,j)$时候(这格还不确定)的轮廓线为$S$的情况(相当于把$(i,1sim j-1)$和$(i-1,jsim m)$的$m$个数用$S$压起来)下有多少种合法方案,然后考虑$(i,j)$这个格子填什么。

    不管怎么样,这格都可以填0,将这个推向$f(i,j+1,S')$。如果左一格或上一格填了1或者这格有障碍,那不能填1,否则可以填1,同理推向$f(i,j+1,S'')$。

    这里的$S'和S''$是位运算将第$j$位进行$0/1$变换的。

    注意考虑细节:一行的轮廓线推完($j$循环到$m$结束后)的这个状态是要作为下一行的起始状态的。也就是$f(i,m,S)$应当推向$f(i+1,1,S')$。

    我们可以通过直接滚动数组来一格一格往下推,避免换行之类的操作,详见code。

    其次,这样DP不需要考虑相邻合不合法,因为我在填的时候推向后面的状态这个操作已经是保证他合法的了,即使是枚举出了不合法的,他的方案数也会是$0$,也没办法有累加作用。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define dbg(x) cerr << #x << " = " << x <<endl
     7 using namespace std;
     8 typedef long long ll;
     9 typedef double db;
    10 typedef pair<int,int> pii;
    11 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    12 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    13 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
    14 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
    15 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
    16 template<typename T>inline T read(T&x){
    17     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    18     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    19 }
    20 const int P=1e8;
    21 int mp[14][14],f[2][1<<12];
    22 int m,n,now,tmp,ans;
    23 
    24 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
    25     read(n),read(m);
    26     for(register int i=1;i<=n;++i)for(register int j=1;j<=m;++j)read(mp[i][j]);
    27     f[0][0]=1;
    28     for(register int i=1;i<=n;++i){
    29         for(register int j=1;j<=m;now^=1,++j){
    30             for(register int k=0;k<1<<m;++k)if(f[now][k]){
    31                 int p2=k&(1<<j-1),p1=j==1?0:k&(1<<j-2);
    32                 tmp=p2?k^(1<<j-1):k,f[now^1][tmp]+=f[now][k],f[now^1][tmp]>=P&&(f[now^1][tmp]-=P);
    33                 if(mp[i][j]&&!p1&&!p2)
    34                     tmp=k|(1<<j-1),f[now^1][tmp]+=f[now][k],f[now^1][tmp]>=P&&(f[now^1][tmp]-=P);
    35                 f[now][k]=0;
    36             }
    37         }
    38     }
    39     for(register int k=0;k<1<<m;++k)ans+=f[now][k],ans>=P&&(ans-=P);
    40     return printf("%d
    ",ans),0;
    41 }
    View Code

    理论$O(nm2^m)$。

  • 相关阅读:
    CentOS6.5配置MySQL主从同步
    CentOS6.5安装telnet
    linux 下安装Google Chrome (ubuntu 12.04)
    jdk w7环境变量配置
    JDBCConnectionException: could not execute query,数据库连接池问题
    注意开发软件的版本问题!
    linux mysql命令行导入导出.sql文件 (ubuntu 12.04)
    linux 下root用户和user用户的相互切换 (ubuntu 12.04)
    linux 下 vim 的使用 (ubuntu 12.04)
    linux 下安装配置tomcat-7 (ubuntu 12.04)
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/11532869.html
Copyright © 2020-2023  润新知