题面

https://www.lydsy.com/JudgeOnline/problem.php?id=4859

题解

和管道取珠类似

首先把平方转化成两条路径经过的图案相同的方案数

对于一条路径 方向一共有8种 分别是 左上 上 右上 左 右 左下 下 右下 (按照起点和终点的位置关系来确定)

我们枚举两个方向 也就是枚举$8 \times 8$ 一共64种方向 注意到对于方向$(a,b)$ 我们发现有其他3种和它是等价的 分别是$(!a,!b),(b,a),(!b,!a)$ (!a 表示a的反方向) 所以实际上只要做$\frac {8 \times 8} {4} =16$种

对于一种情况 我们令$f[a][b][c][d]$表示两条路径的起点分别为$(a,b)$和$(c,d)$的方案数

用记忆化搜索可以算出f数组

然后因为上下左右的四个方向被算了两次 所以得减掉

复杂度$O(16n^4)$

Code

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll; ll read(){
ll x=,f=;char c=getchar();
while(c<'' || c>''){if(c=='-')f=-;c=getchar();}
while(c>='' && c<=''){x=x*+c-'';c=getchar();}
return x*f;
} char get(){
char c=getchar();
while(c!='.' && c!='*') c=getchar();
return c;
} const int mod=1e9+;
int n,m;
char s[][];
int f[][][][],g[][][][];
int dx[][][]={{{-,-,,,},{,,,,},{,,,,}},{{-,,,,},{,,,,},{,,,,}},{{-,-,,,},{,,,,},{,,,,}}},dy[][][]={{{-,,-,,},{-,,,,},{-,,-,,}},{{,,,,},{,,,,},{,,,,}},{{,,,,},{,,,,},{,,,,}}}; inline void pl(int &a,int b){a=a+b;if(a>mod) a-=mod;}
inline void dec(int &a,int b){a=a-b;if(a<) a+=mod;}
int q,w,e,r; int dp(int a,int b,int c,int d){
//cout<<a<<' '<<b<<' '<<c<<' '<<d<<endl;
if(s[a][b]!=s[c][d]) return ;
if(a< || a>n || b< || b>m || c< || c>n || d< || d>m) return ;
if(f[a][b][c][d]) return f[a][b][c][d];
int sum=;
for(int d1=;d1<;d1++){
if(dx[q][w][d1]== && dy[q][w][d1]==) continue;
int nwa=a+dx[q][w][d1],nwb=b+dy[q][w][d1];
for(int d2=;d2<;d2++){
if(dx[e][r][d2]== && dy[e][r][d2]==) continue;
int nwc=c+dx[e][r][d2],nwd=d+dy[e][r][d2];
pl(sum,dp(nwa,nwb,nwc,nwd));
}
}
return f[a][b][c][d]=sum;
} int solve(int a,int b,int c,int d){
if(g[a+][b+][c+][d+]!=) return g[a+][b+][c+][d+];
memset(f,,sizeof(f));
// cout<<a<<' '<<b<<' '<<c<<' '<<d<<endl;
q=a+,w=b+,e=c+,r=d+;
int ret=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
for(int x=;x<=n;x++)
for(int y=;y<=m;y++)
pl(ret,dp(i,j,x,y));
g[a+][b+][c+][d+]=g[c+][d+][a+][b+]=g[-a][-b][-c][-d]=g[-c][-d][-a][-b]=ret;
return ret;
} int solve(int a,int b){
int ans=;
for(int i=-;i<=;i++)
for(int j=-;j<=;j++){
if(i== && j==) continue;
if(i== || j==) dec(ans,solve(a,b,i,j));
else pl(ans,solve(a,b,i,j));
}
return ans;
} int main(){
#ifdef LZT
freopen("in","r",stdin);
freopen("out2","w",stdout);
#endif
n=read(),m=read();
for(int i=;i<=n;i++)
scanf("%s",s[i]+);
int ans=;
for(int i=-;i<=;i++)
for(int j=-;j<=;j++){
if(i== && j==) continue;
if(i== || j==) dec(ans,solve(i,j));
else pl(ans,solve(i,j));
}
printf("%d\n",ans);
return ;
}

Review

1. 注意模数为$10^9+9$ 我一开始写成了$10^9+7$调了半天

最新文章

  1. c# json序列化 意外字符i 意外字符&#239; 解决方案
  2. STM32 MX Cube生成的工程中 使用printf向Uart发送数据
  3. .Net mvc 后台传单引号错误&amp;#39
  4. CSS文本溢出显示省略号
  5. socket基本
  6. 设计模式入门之职责链模式Chain Of Responsibility
  7. C# 实现屏幕键盘 (ScreenKeyboard)
  8. sencha touch环境搭建
  9. win8如何显示文件后缀名
  10. awk说明书(转)
  11. Ubuntu Desktop: 备份与还原
  12. HDU - 6304(2018 Multi-University Training Contest 1) Chiaki Sequence Revisited(数学+思维)
  13. (PMP)第9章-----项目资源管理
  14. 利用 John the Ripper 破解用户登录密码
  15. APUE 12.7 取消选项
  16. TR-069_Amendment-4:附录G.穿越NAT网关的连接请求方式
  17. Java 定时任务 &amp; 任务调度
  18. HDU 1020 Encoding 模拟
  19. zookeeper 事务日志与快照日志
  20. Android下利用RadioGroup和RadioButton实现Tabbar的效果

热门文章

  1. hiho1079 线段树区间改动离散化
  2. 利用ctypes调用Fortran程序
  3. object-c iOS 教程 git for mac
  4. 对云资源服务商资源读写的架构思考:前端代码走token
  5. Sequelize入门一
  6. python模拟登陆discuz论坛
  7. 织梦dedecms页面中增加二维码功能的实现方法
  8. 各种java生成word解决方案的优缺点对比
  9. [yii2]Module的Namespace和控制器位置
  10. LRESULT 数据类型