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\n",ans);
102     return 0;
103 }
View Code

 

posted @ 2018-03-13 10:34  Blue233333  阅读(199)  评论(2编辑  收藏  举报