$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

 //#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
//#include<time.h>
//#include<complex>
#include<algorithm>
#include<stdlib.h>
using namespace std; int n,m,mod,tx,ty;
#define maxn 111
int f[][maxn][maxn][maxn][],cur,sum[maxn][maxn][maxn][],bl[maxn][maxn][]; char s[maxn];
bool mp[maxn][maxn]; //0 up 1 right 2 down 3 left
int main()
{
scanf("%d%d%d%d%d",&n,&m,&mod,&ty,&tx);
for (int i=;i<=n;i++)
{
scanf("%s",s+);
for (int j=;j<=m;j++) mp[i][j]=(s[j]=='+');
} for (int j=;j<=m;j++)
{
bl[][j][]=;
for (int i=;i<=n;i++) if (mp[i][j]) bl[i][j][]=bl[i-][j][];
else bl[i][j][]=i;
}
for (int i=;i<=n;i++)
{
bl[i][m+][]=m+;
for (int j=m;j;j--) if (mp[i][j]) bl[i][j][]=bl[i][j+][];
else bl[i][j][]=j;
}
for (int j=;j<=m;j++)
{
bl[n+][j][]=n+;
for (int i=n;i;i--) if (mp[i][j]) bl[i][j][]=bl[i+][j][];
else bl[i][j][]=i;
}
for (int i=;i<=n;i++)
{
bl[i][][]=;
for (int j=;j<=m;j++) if (mp[i][j]) bl[i][j][]=bl[i][j-][];
else bl[i][j][]=j;
}
cur=; for (int i=;i<=n;i++) sum[m][i][n][]=; int ans=;
for (int L=;L<=ty+;L++)
{
cur^=;
for (int R=m;R>=ty;R--) for (int U=;U<=tx;U++) for (int D=max(U,tx);D<=n;D++)
{
sum[R][U][D][]=sum[R+][U][D][];
f[cur][R][U][D][]=;
if (bl[D][L-][]<U)
{
f[cur][R][U][D][]=sum[R][U][D][];
sum[R][U][D][]+=f[cur][R][U][D][]; sum[R][U][D][]-=sum[R][U][D][]>=mod?mod:;
}
if (L-==ty && U==tx) ans+=f[cur][R][U][D][],ans-=ans>=mod?mod:;
}
if (L==ty+) break;
for (int D=n;D>=tx;D--) for (int R=ty;R<=m;R++) for (int U=;U<=tx+;U++)
{
sum[R][U][D][]=sum[R][U][D+][];
f[cur][R][U][D][]=;
if (bl[U-][L-][]>R)
{
f[cur][R][U][D][]=sum[R][U-][D][];
sum[R][U][D][]+=f[cur][R][U][D][]; sum[R][U][D][]-=sum[R][U][D][]>=mod?mod:;
}
if (U-==tx && R==ty) ans+=f[cur][R][U][D][],ans-=ans>=mod?mod:;
}
for (int D=n;D>=tx;D--) for (int R=ty;R<=m;R++) sum[R][][D][]=sum[R][][D+][];
for (int U=;U<=tx;U++) for (int D=max(tx,U);D<=n;D++) for (int R=ty-;R<m;R++)
{
f[cur][R][U][D][]=;
if (bl[U][R+][]>D)
{
f[cur][R][U][D][]=sum[R+][U][D][];
sum[R][U][D][]+=f[cur][R][U][D][]; sum[R][U][D][]-=sum[R][U][D][]>=mod?mod:;
}
if (D==tx && R+==ty) ans+=f[cur][R][U][D][],ans-=ans>=mod?mod:;
}
for (int U=;U<=tx;U++) for (int D=tx-;D<=n;D++) for (int R=ty;R<=m;R++)
{
if (U) sum[R][U][D][]=sum[R][U-][D][];
f[cur][R][U][D][]=;
if (bl[D+][R][]<L)
{
f[cur][R][U][D][]=sum[R][U][D+][];
sum[R][U][D][]+=f[cur][R][U][D][]; sum[R][U][D][]-=sum[R][U][D][]>=mod?mod:;
}
if (D+==tx && L==ty) ans+=f[cur][R][U][D][],ans-=ans>=mod?mod:;
}
for (int U=;U<=tx;U++) for (int R=ty;R<=m;R++) sum[R][U][n][]=sum[R][U-][n][];
}
printf("%d\n",ans);
return ;
}

最新文章

  1. View 的 focus 和 selected 状态, TabContainer实现
  2. Linux学习笔记2_mysql安装
  3. Android成长日记-Noification实现状态栏通知
  4. java.lang.UnsupportedClassVersionError: xxx/xxxClass : Unsupported major.minor version 51.0
  5. Java基础知识强化68:基本类型包装类之Character概述和Character常见方法
  6. bower安装使用以及git安装
  7. hdu4300之KMP&amp;&amp;EKMP
  8. Byte数组和Int的互相转换
  9. yum 出现错误ImportError: No module named urlgrabber.grabber
  10. 生产环境一键创建kafka集群
  11. MySQL问题汇总
  12. Java 字符串拼接5种方式性能比较
  13. centos安装Django之二:pip3安装
  14. CoreSight™ Technology
  15. 嵌入式系统C编程之堆栈回溯(二)
  16. Node复制文件
  17. php文件每隔几秒执行一次
  18. QNX下进程间通信
  19. Fiddler 调用java webserivces
  20. Linux 入门记录:十八、Linux 系统启动流程 + 单用户修改 root 密码 + GRUB 加密

热门文章

  1. [转]Android专家级别的面试总结
  2. Python调用Java代码部署及初步使用
  3. iOS开发-Runtime详解
  4. Oracle EXPDP and IMPDP
  5. Oracle PL/SQL 编程手册(SQL大全)
  6. 【Win32汇编】编译环境配置
  7. php-PHP Warning: PHP Startup: Invalid library (maybe not a PHP library) &#39;xxx.so&#39; in Unknown on line 0
  8. oracle补丁类型
  9. 背包DP || Codeforces 544C Writing Code
  10. sql is null