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
  • 相关阅读:
    eclipse下载
    maven-jdk版本配置
    winform中的ListBox和ComboBox绑定数据
    C和C#两种方式实现邮件的简单接收
    .Net遍历窗体上控件
    C和C#两种方式实现邮件的简单发送
    Gtk基础学习总结(二)
    Gtk基础学习总结(一)
    你要知道的C与C++的区别
    C程序中引用自定义的C函数模块
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8554535.html
Copyright © 2011-2022 走看看