~~~题面~~~

题解:

  首先观察到题目要求的是合法回文串的个数,而回文串要求从前往后和从后往前是一样的,因此我们假设有两只猪,分别从左上和右下开始走,走相同的步数最后相遇,那么它们走的路能拼在一起构成一个回文串,当且仅当它们走字符串是完全相同的。

  那么我们可以根据这个性质进行DP,设f[i][j][k][l]表示第一只猪走到(i, j),第二只猪走到(k, l)的方案数。

  那么观察到$i + j = k + l$,所以$l$是没必要记录的,因为前面三个确定,l就确定了,然后因为i从1 开始枚举,每次只能走一步,所以只会用到上一步的方案,所以可以滚动一下,这样时空复杂度就都可以承受了。

  因为要限制两只猪走的步数一样,注意限制第一只猪在红色的三角形中,另一只猪在蓝色的三角形中。

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 510
#define mod 1000000007
#define LL long long int n, m;
LL f[][AC][AC], ans;
char s[AC][AC]; void pre()
{
scanf("%d%d", &n, &m);
for(R i = ; i <= n; i ++) scanf("%s", s[i] + );
if(s[][] != s[n][m]) {printf("0\n"); exit();}
} inline bool check(int i, int j, int k, int l)
{
if(i == k && j == l) return true;
else if(i + == k && j == l) return true;
else if(i == k && j + == l) return true;
return false;
} void work()
{
int l, now = , b = (n + m) / ;
f[][][n] = ;
for(R i = ; i <= n; i ++, now ^= )
{
for(R j = ; j + i - <= b; j ++)
{
if(i == && j == ) continue;
for(R k = n; k >= i; k --)
{
l = n + m + - i - j - k;
if(l < j || l > m) continue;
if(s[i][j] != s[k][l]) continue;
f[now][j][k] = f[now ^ ][j][k] + f[now ^ ][j][k + ];
f[now][j][k] += f[now][j - ][k] + f[now][j - ][k + ];
f[now][j][k] %= mod;
if(check(i, j, k, l)) ans += f[now][j][k];
if(ans > mod) ans -= mod;
}
}
memset(f[now ^ ], , sizeof(f[now ^ ]));//因为有同层转移,所以要memset,而不能枚举到它的时候再重置
}
printf("%lld\n", ans);
} void work1()
{
int l, now = , b = (n + m) / ;
f[][][n] = ;
for(R i = ; i <= n; i ++, now ^= )
{
for(R j = ; j + i - <= b; j ++)
{
if(i == && j == ) continue;
for(R k = n; k >= i; k --)
{
l = n + m + - i - j - k;
if(l < j || l > m) continue;
if(s[i][j] != s[k][l]) continue;
f[i][j][k] += f[i - ][j][k] + f[i - ][j][k + ];
f[i][j][k] += f[i][j - ][k] + f[i][j - ][k + ];
f[i][j][k] %= mod;
if(check(i, j, k, l)) ans += f[i][j][k];
if(ans > mod) ans -= mod;
}
}
}
printf("%lld\n", ans);
} int main()
{
// freopen("in.in", "r", stdin);
pre();
work();
// fclose(stdin);
return ;
}

最新文章

  1. iOS开发小技巧--计算label的Size的方法总结
  2. NodeJS Hello world
  3. 浅谈RSA加密算法
  4. angularjs中ng-route和ui-router简单用法的代码比较
  5. Android解惑 - 为什么要用Fragment.setArguments(Bundle bundle)来传递参数(转)
  6. Struts2六、为应用指定多个配置文件
  7. crawler_基础之_java.net.HttpURLConnection 访问网络资源
  8. TensorFlow windows 安装(base anaconda)
  9. 全角的空格(A1A1)惹的祸!
  10. Linux的notifier机制在TP中的应用【转】
  11. Kali Day01 --- arpspoof命令进行断网攻击(ARP欺骗)
  12. layui小封装方法
  13. vue 使用element-ui upload文件上传之后怎么清空
  14. Oracle存储过程入参传入List集合的小例子
  15. Timer应用之Interval优化
  16. PL/SQL轻量版(三)——游标与异常处理
  17. 【Openwrt】刷
  18. 使用putty远程登录Ubuntu时,报Network error:Connection refused错误
  19. Python内置函数之input()
  20. Sql注入基础_mysql注入

热门文章

  1. 【ppp-chap,pap,mp,mp-group】
  2. pyecharts数据分析及展示
  3. python基础知识 -- set集合
  4. Leecode刷题之旅-C语言/python-70爬楼梯
  5. Preparing Cities for Robot Cars【城市准备迎接自动驾驶汽车】
  6. web视频播放
  7. 利用nodejs实现商品管理系统(二)
  8. Git使用之二:下载远程代码到本地指定文件夹
  9. windows 无法上网问题解决一例
  10. 「学习记录」《数值分析》第二章计算实习题(Python语言)