• 2331: [SCOI2011]地板 插头DP


    国际惯例的题面:

    十分显然的插头DP。由于R*C<=100,所以min(R,C)<=10,然后就可以愉悦地状压啦。
    我们用三进制状压,0表示没有插头,1表示有一个必须延伸至少一格且拐弯的插头,2表示有一个必须延伸一格且不可以拐弯的插头。
    转移的话就十分显然了。
    00->22,表示用这个格子作为开始的拐角。
    00->10,表示用这个格子向下延伸。
    00->01,表示用这个格子向右延伸。
    01->10,表示这个格子连接上下。
    01->02,表示在这个格子作为中间的拐角。
    02->20,表示这个格子连接上下。
    02->00,表示这个格子作为某个地板的终点。
    10->01,表示这个格子连接左右。
    10->20,表示在这个格子作为中间的拐角。
    11->00,表示这个格子作为结束的拐角。
    20->00,表示这个格子作为某个地板的终点。
    20->02,表示这个格子连接左右。
    (插头DP的本质就是分类讨论,所以麻烦也没办法,想明白就很容易了)
    然后就是实现了。我是用unordered_map存储状态,同时先找到第一个可以放东西的位置开始DP,统计答案的时候统计第n+1行没有插头的状态。

    代码:

     1 #pragma GCC optimize(2)
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<tr1/unordered_map>
     5 using namespace std;
     6 using namespace tr1;
     7 const int maxn=1e2+1e2;
     8 const int mod=20110520;
     9 
    10 int sta[maxn],nxt[maxn];
    11 char in[maxn][maxn]; // in == 1 means empty .
    12 int n,m,cur,fx,fy;
    13 unordered_map<int,int> f[2];
    14 
    15 inline void unzip(int* sta,int ss) {
    16     for(int i=m+1;i;i--) sta[i] = ss % 3 , ss /= 3;
    17 }
    18 inline int zip(int* sta) {
    19     int ret = 0;
    20     for(int i=1;i<=m+1;i++) ret = ret * 3 + sta[i];
    21     return ret;
    22 }
    23 
    24 inline void core_trans(unordered_map<int,int> &dst,int x,int y,int add) {
    25     memcpy(nxt,sta,sizeof(int)*(m+2));
    26     if( !in[x][y] ) { // not empty .
    27         if( sta[y] == 0 && sta[y+1] == 0 ) ( dst[zip(nxt)] += add ) %= mod;
    28         return;
    29     }
    30     if( sta[y] == 0 ) {
    31         if( sta[y+1] == 0 ) {
    32             nxt[y] = 2 , nxt[y+1] = 2 , ( dst[zip(nxt)] += add ) %= mod;
    33             nxt[y] = 1 , nxt[y+1] = 0 , ( dst[zip(nxt)] += add ) %= mod;
    34             nxt[y] = 0 , nxt[y+1] = 1 , ( dst[zip(nxt)] += add ) %= mod;
    35         } else if( sta[y+1] == 1 ) {
    36             nxt[y] = 1 , nxt[y+1] = 0 , ( dst[zip(nxt)] += add ) %= mod;
    37             nxt[y] = 0 , nxt[y+1] = 2 , ( dst[zip(nxt)] += add ) %= mod;
    38         } else if( sta[y+1] == 2 ) {
    39             nxt[y] = 2 , nxt[y+1] = 0 , ( dst[zip(nxt)] += add ) %= mod;
    40             nxt[y] = 0 , nxt[y+1] = 0 , ( dst[zip(nxt)] += add ) %= mod;
    41         }
    42     } else if( sta[y] == 1 ) {
    43         if( sta[y+1] == 0 ) {
    44             nxt[y] = 0 , nxt[y+1] = 1 , ( dst[zip(nxt)] += add ) %= mod;
    45             nxt[y] = 2 , nxt[y+1] = 0 , ( dst[zip(nxt)] += add ) %= mod;
    46         } else if( sta[y+1] == 1 ) nxt[y] = 0 , nxt[y+1] = 0 , ( dst[zip(nxt)] += add ) %= mod;
    47     } else if( sta[y] == 2 ) {
    48         if( sta[y+1] == 0 ) {
    49             nxt[y] = 0 , nxt[y+1] = 0 , ( dst[zip(nxt)] += add ) %= mod;
    50             nxt[y] = 0 , nxt[y+1] = 2 , ( dst[zip(nxt)] += add ) %= mod;
    51         }
    52     }
    53 }
    54 inline void trans(const unordered_map<int,int> &sou,unordered_map<int,int> &dst,int x,int y) {
    55     dst.clear();
    56     for(unordered_map<int,int>::const_iterator it=sou.begin();it!=sou.end();it++) if( it->second ) {
    57         unzip(sta,it->first) , core_trans(dst,x,y,it->second);
    58     }
    59 }
    60 inline void transline(const unordered_map<int,int> &sou,unordered_map<int,int> &dst) {
    61     dst.clear();
    62     for(unordered_map<int,int>::const_iterator it=sou.begin();it!=sou.end();it++) if( it->second && ! ( it->first % 3 ) ) {
    63         dst[it->first/3] = it->second;
    64     }
    65 }
    66 
    67 inline void revert() { // make m <= n .
    68     static char tp[maxn][maxn];
    69     memcpy(tp,in,sizeof(in)) , memset(in,0,sizeof(in));
    70     for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) in[j][i] = tp[i][j];
    71     swap(n,m);
    72 }
    73 
    74 int main() {
    75     scanf("%d%d",&n,&m) , fx = -1 , fy = -1;
    76     for(int i=1;i<=n;i++) {
    77         scanf("%s",in[i]+1);
    78         for(int j=1;j<=m;j++) in[i][j] = in[i][j] == '_';
    79     }
    80     
    81     if( n < m ) revert();
    82     for(int i=1;i<=n&&!~fx;i++) for(int j=1;j<=m&&!~fx;j++) if(in[i][j]) fx = i , fy = j;
    83     if( !~fx ) return puts("1") , 0; // nothing to do .
    84     sta[fy] = 0 , sta[fy+1] = 1 , f[cur][zip(sta)] = 1;
    85     sta[fy] = 1 , sta[fy+1] = 0 , f[cur][zip(sta)] = 1;
    86     sta[fy] = sta[fy+1] = 2 , f[cur][zip(sta)] = 1;
    87     for(int j=fy+1;j<=m;j++) trans(f[cur],f[cur^1],fx,j) , cur ^= 1;
    88     transline(f[cur],f[cur^1]) , cur ^= 1;
    89     
    90     for(int i=fx+1;i<=n;i++) {
    91         for(int j=1;j<=m;j++)
    92             trans(f[cur],f[cur^1],i,j) , cur ^= 1;
    93         transline(f[cur],f[cur^1]) , cur ^= 1;
    94     }
    95     
    96     printf("%d
    ",f[cur][0]);
    97     
    98     return 0;
    99 }
    View Code



    たいせつなきみのために ぼくにできるいちばんのことは
    为了最重要的你 我所能做的最好的事
    約束を忘れること君への想い消し去ること
    就是忘却与你的约定抹去对你的思念
    沈む夕日暮れてく空 夜の帳舞い降りる頃
    渐渐归隐大地的夕阳 夜幕降临整个天空 夜的气息轻盈飘落之时
    僕は目を閉じて それは闇に溶けるように 滲んで消えた
    我闭目去感受 一切就像溶入暗影一样 渗透进去消散无痕了

    未来なんていらないよ
    未来(明日)什么的已经不需要了吧
    君が側にいる過去のままで
    因为有你一直陪伴我的往昔(昨日)

  • 相关阅读:
    react 添加addEventListener事件
    C#中 Queue List LinkedList 性能对比
    Nginx中proxy_pass的斜杠(/)问题
    原码,补码和反码
    Base64原理
    springsessiondataredis session同步的使用
    中间件redis常用命令
    java项目中的classpath的理解
    linux环境oracle设置环境变量
    Redis 主从复制的原理及演进
  • 原文地址:https://www.cnblogs.com/Cmd2001/p/9043222.html
Copyright © 2020-2023  润新知