zoukankan      html  css  js  c++  java
  • BZOJ1126: [POI2008]Uci

    $n leq 100,m leq 100$,$n*m$的01矩形,问从左下角开始往上走,每次转弯只能向右,不能经过重复点,不能撞到1,到达点$(x,y)$的方案数,$mod k$。

    感人肺腑的细节题写了一天。。

    可以发现他在做一个绕圈运动,运动的过程中逐渐限制自己的活动范围,因此可以用活动范围和射入方向表示状态(这样也就确定了它的位置),$f[L][R][U][D][0123]$--沿左边向上、沿上边向右、沿右边向下、沿下边向左射入矩形$[L,R,U,D]$的方案。如图:

    这样转移可以用一个前缀和转移。比如上转右的:

    用纵方向一个前缀的蓝色矩形转移到右方向的一个矩形。这样就可以$O(1)$转移了。

    由于四维开不下,要把L那一维滚动掉,所以记前缀和的时候,左转上那个数组不要清,那里实际保留了所有$L_2<L$转移到$L$的状态的前缀和。

    记答案的时候,在目标处转弯时记录答案。注意最后一圈不要记重了。这句话是啥意思我也说不清,看代码吧QAQ

      1 //#include<iostream>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<cstdio>
      5 //#include<time.h>
      6 //#include<complex>
      7 #include<algorithm>
      8 #include<stdlib.h>
      9 using namespace std;
     10 
     11 int n,m,mod,tx,ty;
     12 #define maxn 111
     13 int f[2][maxn][maxn][maxn][4],cur,sum[maxn][maxn][maxn][4],bl[maxn][maxn][4]; char s[maxn];
     14 bool mp[maxn][maxn]; //0 up 1 right 2 down 3 left
     15 int main()
     16 {
     17     scanf("%d%d%d%d%d",&n,&m,&mod,&ty,&tx);
     18     for (int i=1;i<=n;i++)
     19     {
     20         scanf("%s",s+1);
     21         for (int j=1;j<=m;j++) mp[i][j]=(s[j]=='+');
     22     }
     23     
     24     for (int j=1;j<=m;j++)
     25     {
     26         bl[0][j][0]=0;
     27         for (int i=1;i<=n;i++) if (mp[i][j]) bl[i][j][0]=bl[i-1][j][0];
     28         else bl[i][j][0]=i;
     29     }
     30     for (int i=1;i<=n;i++)
     31     {
     32         bl[i][m+1][1]=m+1;
     33         for (int j=m;j;j--) if (mp[i][j]) bl[i][j][1]=bl[i][j+1][1];
     34         else bl[i][j][1]=j;
     35     }
     36     for (int j=1;j<=m;j++)
     37     {
     38         bl[n+1][j][2]=n+1;
     39         for (int i=n;i;i--) if (mp[i][j]) bl[i][j][2]=bl[i+1][j][2];
     40         else bl[i][j][2]=i;
     41     }
     42     for (int i=1;i<=n;i++)
     43     {
     44         bl[i][0][3]=0;
     45         for (int j=1;j<=m;j++) if (mp[i][j]) bl[i][j][3]=bl[i][j-1][3];
     46         else bl[i][j][3]=j;
     47     }
     48     cur=0; for (int i=1;i<=n;i++) sum[m][i][n][0]=1;
     49         
     50     int ans=0;
     51     for (int L=2;L<=ty+1;L++)
     52     {
     53         cur^=1;
     54         for (int R=m;R>=ty;R--) for (int U=1;U<=tx;U++) for (int D=max(U,tx);D<=n;D++)
     55         {
     56             sum[R][U][D][1]=sum[R+1][U][D][1];
     57             f[cur][R][U][D][1]=0;
     58             if (bl[D][L-1][0]<U)
     59             {
     60                 f[cur][R][U][D][1]=sum[R][U][D][0];
     61                 sum[R][U][D][1]+=f[cur][R][U][D][1]; sum[R][U][D][1]-=sum[R][U][D][1]>=mod?mod:0;
     62             }
     63             if (L-1==ty && U==tx) ans+=f[cur][R][U][D][1],ans-=ans>=mod?mod:0;
     64         }
     65         if (L==ty+1) break;
     66         for (int D=n;D>=tx;D--) for (int R=ty;R<=m;R++) for (int U=2;U<=tx+1;U++)
     67         {
     68             sum[R][U][D][2]=sum[R][U][D+1][2];
     69             f[cur][R][U][D][2]=0;
     70             if (bl[U-1][L-1][1]>R)
     71             {
     72                 f[cur][R][U][D][2]=sum[R][U-1][D][1];
     73                 sum[R][U][D][2]+=f[cur][R][U][D][2]; sum[R][U][D][2]-=sum[R][U][D][2]>=mod?mod:0;
     74             }
     75             if (U-1==tx && R==ty) ans+=f[cur][R][U][D][2],ans-=ans>=mod?mod:0;
     76         }
     77         for (int D=n;D>=tx;D--) for (int R=ty;R<=m;R++) sum[R][1][D][2]=sum[R][1][D+1][2];
     78         for (int U=1;U<=tx;U++) for (int D=max(tx,U);D<=n;D++) for (int R=ty-1;R<m;R++)
     79         {
     80             f[cur][R][U][D][3]=0;
     81             if (bl[U][R+1][2]>D)
     82             {
     83                 f[cur][R][U][D][3]=sum[R+1][U][D][2];
     84                 sum[R][U][D][3]+=f[cur][R][U][D][3]; sum[R][U][D][3]-=sum[R][U][D][3]>=mod?mod:0;
     85             }
     86             if (D==tx && R+1==ty) ans+=f[cur][R][U][D][3],ans-=ans>=mod?mod:0;
     87         }
     88         for (int U=1;U<=tx;U++) for (int D=tx-1;D<=n;D++) for (int R=ty;R<=m;R++)
     89         {
     90             if (U) sum[R][U][D][0]=sum[R][U-1][D][0];
     91             f[cur][R][U][D][0]=0;
     92             if (bl[D+1][R][3]<L)
     93             {
     94                 f[cur][R][U][D][0]=sum[R][U][D+1][3];
     95                 sum[R][U][D][0]+=f[cur][R][U][D][0]; sum[R][U][D][0]-=sum[R][U][D][0]>=mod?mod:0;
     96             }
     97             if (D+1==tx && L==ty) ans+=f[cur][R][U][D][0],ans-=ans>=mod?mod:0;
     98         }
     99         for (int U=1;U<=tx;U++) for (int R=ty;R<=m;R++) sum[R][U][n][0]=sum[R][U-1][n][0];
    100     }
    101     printf("%d
    ",ans);
    102     return 0;
    103 }
    View Code
  • 相关阅读:
    使用BIOS进行键盘输入和磁盘读写03 零基础入门学习汇编语言77(完)
    Android通过JNI调用驱动程序(完全解析实例)
    Android的七巧板Activity之二 Activity的加载模式
    JAVA Integer进制的转换
    转载文章:Microsoft 将僵尸网络威胁智能分析程序引入云中以提供近实时数据
    WindowManager实现悬浮窗口&可自由移动的悬浮窗口
    Android中实现“程序前后台切换效果”和“返回正在运行的程序,而不是一个新Activity”
    Android功能总结:仿照Launcher的Workspace实现左右滑动切换
    Android WebView缓存
    现在接受参加国际创业节 DOer Express的 申请
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8554535.html
Copyright © 2011-2022 走看看