zoukankan      html  css  js  c++  java
  • bzoj2331 [SCOI2011]地板

    Description

    lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西。小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板。现在小L想知道,用L型的地板铺满整个客厅有多少种不同的方案?

    需要注意的是,如下图所示,L型地板的两端长度可以任意变化,但不能长度为0。铺设完成后,客厅里面所有没有柱子的地方都必须铺上地板,但同一个地方不能被铺多次。

    Input

    输入的第一行包含两个整数,R和C,表示客厅的大小。

    接着是R行,每行C个字符。’_’表示对应的位置是空的,必须铺地板;’*’表示对应的位置有柱子,不能铺地板。

    Output

    输出一行,包含一个整数,表示铺满整个客厅的方案数。由于这个数可能很大,只需输出它除以20110520的余数。

    Sample Input

    2 2
    *_
    __

    Sample Output

    1

    HINT

    R*C<=100

    正解:插头$dp$。

    插头$dp$第一题,写了巨久。。

    这道题还是比较裸的,我们把轮廓线的状态分为$3$种情况,没有插头,插头没拐弯,插头已经拐过弯了,然后就很好转移了。

    在每一行的最后一个格子转移的时候要特判。轮廓线到下一行要左移一位。注意用$4$进制比$3$进制常数更小,$4$进制状态较大,所以要手写$hash$。

     1 #include <bits/stdc++.h>
     2 #define ll long long
     3 #define RG register
     4 #define il inline
     5 #define M (1<<22)
     6 #define rhl (20110520)
     7 #define w(s,p) ((s)>>((p)<<1)&3)
     8 #define upd(s,p,v) ((s)^(w(s,p)<<((p)<<1))^((v)<<((p)<<1)))
     9 
    10 using namespace std;
    11 
    12 int vis[M],S[2][M],f[2][M],sz[M],g[110][110],n,m,pre,cur,ans;
    13 
    14 il char gc(){
    15   RG char ch=getchar();
    16   while (ch!='*' && ch!='_') ch=getchar(); return ch;
    17 }
    18 
    19 il void add(RG int s,RG int v){
    20   if (vis[s]){
    21     f[cur][vis[s]]+=v;
    22     if (f[cur][vis[s]]>=rhl) f[cur][vis[s]]-=rhl;
    23     return;
    24   }
    25   vis[s]=++sz[cur],S[cur][sz[cur]]=s,f[cur][sz[cur]]=v; return;
    26 }
    27 
    28 int main(){
    29 #ifndef ONLINE_JUDGE
    30   freopen("floor.in","r",stdin);
    31   freopen("floor.out","w",stdout);
    32 #endif
    33   cin>>n>>m;
    34   for (RG int i=1;i<=n;++i)
    35     for (RG int j=1;j<=m;++j)
    36       if (n>=m) g[i][j]=gc()=='_'; else g[j][i]=gc()=='_';
    37   if (n<m) swap(n,m); sz[0]=f[0][1]=1;
    38   for (RG int i=1;i<=n;++i){
    39     for (RG int k=1;k<=sz[cur];++k) (S[cur][k]<<=2)&=(1<<((m+1)<<1))-1;
    40     for (RG int j=1;j<=m;++j){
    41       pre=cur,sz[cur^=1]=0;
    42       if (!g[i][j]){
    43     for (RG int k=1;k<=sz[pre];++k)
    44       if (!w(S[pre][k],j-1) && !w(S[pre][k],j) && f[pre][k]) add(S[pre][k],f[pre][k]);
    45     for (RG int k=1;k<=sz[cur];++k) vis[S[cur][k]]=0; continue;
    46       }
    47       for (RG int k=1,x,y,s,v;k<=sz[pre];++k){
    48     s=S[pre][k],v=f[pre][k]; if (!v) continue;
    49     x=w(s,j-1),y=w(s,j);
    50     if (!x && !y){
    51       if (g[i][j+1]) add(upd(upd(s,j-1,0),j,1),v);
    52       if (g[i+1][j]) add(upd(upd(s,j-1,1),j,0),v);
    53       if (g[i][j+1] && g[i+1][j]) add(upd(upd(s,j-1,2),j,2),v);
    54     }
    55     if (!x && y==1){
    56       if (g[i+1][j]) add(upd(upd(s,j-1,1),j,0),v);
    57       if (g[i][j+1]) add(upd(upd(s,j-1,0),j,2),v);
    58     }
    59     if (x==1 && !y){
    60       if (g[i][j+1]) add(upd(upd(s,j-1,0),j,1),v);
    61       if (g[i+1][j]) add(upd(upd(s,j-1,2),j,0),v);
    62     }
    63     if (!x && y==2){
    64       add(upd(upd(s,j-1,0),j,0),v);
    65       if (g[i+1][j]) add(upd(upd(s,j-1,2),j,0),v);
    66     }
    67     if (x==2 && !y){
    68       add(upd(upd(s,j-1,0),j,0),v);
    69       if (g[i][j+1]) add(upd(upd(s,j-1,0),j,2),v);
    70     }
    71     if (x==1 && y==1) add(upd(upd(s,j-1,0),j,0),v);
    72       }
    73       for (RG int k=1;k<=sz[cur];++k) vis[S[cur][k]]=0;
    74     }
    75   }
    76   for (RG int i=1;i<=sz[cur];++i) if (!S[cur][i]) ans=f[cur][i];
    77   cout<<ans; return 0;
    78 }
  • 相关阅读:
    Java入门——day28
    第四周进度报告
    Java入门——day27
    Java入门——day26
    Java入门——day25
    Java入门——day24
    Ubuntu创建新用户
    SpringBoot默认的Servlet容器是自带的Tomcat,如何定制和修改配置
    哈希
    找到两张相似的图
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7689215.html
Copyright © 2011-2022 走看看