E. Pig and Palindromes

Peppa the Pig was walking and walked into the forest. What a strange coincidence! The forest has the shape of a rectangle, consisting of n rows and m columns. We enumerate the rows of the rectangle from top to bottom with numbers from 1 to n, and the columns — from left to right with numbers from 1 to m. Let’s denote the cell at the intersection of the r-th row and the c-th column as (r, c).

Initially the pig stands in cell (1, 1), and in the end she wants to be in cell (n, m). Since the pig is in a hurry to get home, she can go from cell (r, c), only to either cell (r + 1, c) or (r, c + 1). She cannot leave the forest.

The forest, where the pig is, is very unusual. Some cells of the forest similar to each other, and some look very different. Peppa enjoys taking pictures and at every step she takes a picture of the cell where she is now. The path through the forest is considered to be beautiful if photographs taken on her way, can be viewed in both forward and in reverse order, showing the same sequence of photos. More formally, the line formed by the cells in order of visiting should be a palindrome (you can read a formal definition of a palindrome in the previous problem).

Count the number of beautiful paths from cell (1, 1) to cell (n, m). Since this number can be very large, determine the remainder after dividing it by 109 + 7.

Input

The first line contains two integers n, m (1 ≤ n, m ≤ 500) — the height and width of the field.

Each of the following n lines contains m lowercase English letters identifying the types of cells of the forest. Identical cells are represented by identical letters, different cells are represented by different letters.

Output

Print a single integer — the number of beautiful paths modulo 109 + 7.

Sample test(s)

input

3 4

aaab

baaa

abba

output

3

题意概述:在一个n*m的矩阵中,每个格子都有一个字母。你从(1,1)出发前往(n,m),每次仅仅能向下或向右。当到达终点时,把你经过的字母写下来。产生一个字符串。求有多少种走成回文的方案。

每一次仅仅能向下或向右。所以考虑能够用dp做。考虑曼哈顿距离

按距离原点和终点的曼哈顿距离同样的两个点做状态转移

想象有两个点分别从起点和终点同一时候向中间走

用f[p1][p2] 表示 第一个点在p1位置第二个点在p2位置时的从起点终点同一时候走过的同样字母路径的合法状态数

f[p1][p2]=f[p1_f1][p2_f1]+f[p1_f1][p2_f2]+f[p1_f2][p2_f1]+f[p1_f2][p2_f2]

p1_f1,p1_f2,p2_f1,p2_f2分别表示p1和p2的前驱点

因为坐标非常大,须要用滚动数组优化。斜着循环每个点也须要一些小技巧详细看代码~

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
const int MAX=505;
const int MOD=1e9+7;
char s[MAX][MAX];
int f[MAX][MAX]={0};
int f_[MAX][MAX];
int i,j,m,n,k,dis;
struct point{
int x,y;
};
point next_1(point a)
{
if (a.y==1&&a.x<n)
a.x++;
else
a.y++;
return a;
}
point next_2(point a)
{
if (a.x==n&&a.y>1)
a.y--;
else
a.x--;
return a;
}
point nex(point a)
{
a.x--;
a.y++;
return a;
}
int main()
{
cin>>n>>m;
int ans=0;
getchar();
for (i=1;i<=n;i++)
{
for (j=1;j<=m;j++)
scanf("%c",&s[i][j]);
getchar();
}
point a,b,p1,p2;
a.x=a.y=1;
b.x=n;b.y=m;
int max_=(m+n)/2;
if (s[1][1]==s[n][m])
f[1][n]=1;
else
f[1][n]=0;
if (m+n<=3)
{
cout<<f[1][n]<<endl;
return 0;
}
for (dis=2;dis<=max_;dis++)
{
a=next_1(a);
b=next_2(b);
for (i=1;i<=500;i++)
for (j=1;j<=500;j++)
{
f_[i][j]=f[i][j];
f[i][j]=0;
}
for (p1=a;p1.y<=m&&p1.x>=1;p1=nex(p1))
for (p2=b;p2.y<=m&&p2.x>=1;p2=nex(p2))
if (s[p1.x][p1.y]==s[p2.x][p2.y])
{
f[p1.x][p2.x]=((f_[p1.x-1][p2.x]+f_[p1.x-1][p2.x+1])%MOD+(f_[p1.x][p2.x]+f_[p1.x][p2.x+1])%MOD)%MOD;
if (((p1.x==p2.x)&&(abs(p1.y-p2.y)<=1))||((p1.y==p2.y)&&(abs(p1.x-p2.x)<=1)))
ans=(ans+f[p1.x][p2.x])%MOD;
}
}
cout<<ans<<endl;
return 0;
}

贴一个cf上看到的位运算的程序,相当简短

#include <bits/stdc++.h>
using namespace std;
#define f(i,n) for(int i=0;i<(n);i++)
#define fr(i,n) for(int i=n;i--;)
char x[500][501];
int d[2][501][501],n,m;
main(){
cin>>n>>m;
f(i,n) cin>>x[i];
f(ei,n) fr(si,n) fr(sj,m){
auto& c=d[ei&1][si][sj]=0,ej=n+m-2-si-sj-ei;
if(si<=ei&&sj<=ej&&x[si][sj]==x[ei][ej]&&!(c=abs(si-ei)+abs(sj-ej)<=1))
f(i,2) f(j,2) c=(c+d[ei-!j&1][si+!i][sj+!!i])%((int)1e9+7);
}
cout<<d[~n&1][0][0]<<'\n';
}

CF 316div2 E.Pig and Palindromes的更多相关文章

  1. codeforces 570 E. Pig and Palindromes (DP)

    题目链接: 570 E. Pig and Palindromes 题目描述: 有一个n*m的矩阵,每个小格子里面都有一个字母.Peppa the Pig想要从(1,1)到(n, m).因为Peppa ...

  2. Codeforces Round #316 (Div. 2)E. Pig and Palindromes DP

    E. Pig and Palindromes   Peppa the Pig was walking and walked into the forest. What a strange coinci ...

  3. 【25.64%】【codeforces 570E】Pig and Palindromes

    time limit per test4 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  4. Codeforces 570E - Pig and Palindromes - [滚动优化DP]

    题目链接:https://codeforces.com/problemset/problem/570/E 题意: 给出 $n \times m$ 的网格,每一格上有一个小写字母,现在从 $(1,1)$ ...

  5. D Tree Requests dfs+二分 D Pig and Palindromes -dp

    D time limit per test 2 seconds memory limit per test 256 megabytes input standard input output stan ...

  6. CF570E Pig and Palindromes

    完全不会这种类型的$dp$啊…… 考虑回文串一定是可以拆分成(偶数个字母 + 偶数个字母)或者(偶数个字母 + 一个字母 +偶数个字母),两边的偶数个字母其实是完全对称的.因为这道题回文串的长度是给定 ...

  7. CodeForces 570E DP Pig and Palindromes

    题意:给出一个n行m列的字符矩阵,从左上角走到右下角,每次只能往右或者往下走,求一共有多少种走法能得到回文串. 分析: 可以从两头开始考虑,每次只走一样字符的格子,这样得到的两个字符串拼起来之后就是一 ...

  8. Codeforces 570 - A/B/C/D/E - (Done)

    链接:https://codeforces.com/contest/570 A - Elections - [水] AC代码: #include<bits/stdc++.h> using ...

  9. CF 568A(Primes or Palindromes?-暴力推断)

    A. Primes or Palindromes? time limit per test 3 seconds memory limit per test 256 megabytes input st ...

随机推荐

  1. luogu P1038借教室【Noip提高组2012】

    这道题我读完题目的第一感觉是: 这不就是个线段树??用线段树维护区间最小值,检查是否满足订单要求即可判断. 对于修改操作直接在区间上进行. 据说会卡一卡线段树,但是貌似写一个懒标记,连zkw线段树都不 ...

  2. 数据排序 第二讲( 各种排序方法 结合noi题库1.10)

    先来个题练练手吧! 例题 04:奖学金 查看 提交 统计 提问 总时间限制:  1000ms 内存限制:  65536kB 描述 某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生 ...

  3. 6、Django实战第6天:用户登录

    今天开始,我们需要来写后台逻辑了.... 后台逻辑代码都是编写在views.py文件里面,今天要完成的登录功能,因此来编辑users.views.py 这里我们根据请求方法来判断分为2种情况,网页默认 ...

  4. Eclipse Build all and build project not working - jar missing

    Eclipse Build all and build project not working - jar missing

  5. 去掉Chrome手机版首屏的“推荐的文章”

    百度可得很多类似的文章,然而都是失效的,,比如此文,本文演示所使用的Chrome版本为59. 百度所得的解决办法都是同一个,排版,截图都是一样的,害我浪费了不少力气. 第一,转载文章未标明文章出处: ...

  6. APP换肤

    一.需求说明 当一个APP用户量大的时候,就需要给不同的用户做标签,用来彰显身份.比如QQ的会员,VIP等不同的皮肤功能. 二.实现方法. 所谓不同的皮肤,就是不同的权限(身份)显示不同的本地或者网络 ...

  7. [Atcoder Grand Contest 001] Tutorial

    Link: AGC001 传送门 A: …… #include <bits/stdc++.h> using namespace std; ; ]; int main() { scanf(& ...

  8. [BZOJ 2208] 连通数

    Link: BZOJ 2208 连通数 Solution: 传递闭包模板题 传递闭包是集合中最小的二元关系,其实就是对二元关系的不断拓展,一般用$floyd$求解 这里要先跑一遍$tarjan$求出$ ...

  9. [AGC012D]Colorful Balls

    题意:有$N$个球,有颜色$c_i$,重量$w_i$,若($c_a=c_b$且$w_a+w_b\leq X$)或($c_a\ne c_b$且$w_a+w_b\leq Y$),可以交换$a,b$,求总共 ...

  10. iOS 修改APP工程名字

    我们在iOS开发中,难免会遇到项目做到一半要改名字的情况.如果项目名差的太大,工程名看起来总是不舒服的,就会想着为工程改个贴切的名字,那么你就为用到本文记录的内容. 如何修改工程名呢? 下面我就拿一个 ...