570E Pig and Palindromes(#316 (Div. 2))dp**

E. Pig and Palindromes
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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 bebeautiful 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
Note

Picture illustrating possibilities for the sample test.

題意:給字符矩陣,求從左上角走到右下角,能組成迴文串的路徑數。

思路:由於走出的路線是個迴文串,不妨考慮從左上角和右下角同時出發同時走動,要求每一步都走到相同的字符,令dp[i][j][k]爲路徑長度爲i,左上角出發走到y座標爲j,右下角出發走到y座標爲k的方案數,可以根據路徑長度計算出兩個方向當前位置的座標,如果當前位置字符相同,枚舉兩條路徑的上一個位置,一共4種可能,如果字符相等就可以轉移到當前狀態,如果最終字符串長度爲奇數,則要求走到同一個格子,否則要走到相鄰格子,可以根據y座標的值來判定,統計答案即可,時間複雜度是O(n^3)的,dp的第一維是路徑長度,可以滾動起來,空間複雜度是O(n^2)的。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<stdio.h>
#include<math.h>
#include <string>
#include<string.h>
#include<map>
#include<queue>
#include<set>
#include<vector>
#include<algorithm>
#include<stdlib.h>
using namespace std;
#define eps 1e-8
#define inf 0x3f3f3f3f
#define rd(x) scanf("%d",&x)
#define rd2(x,y) scanf("%d%d",&x,&y)
#define ll long long int
#define mod 1000000007
#define maxn 505
#define maxm 500010
int d[4][2]={0,1,1,0,-1,0,0,-1};
ll dp[2][505][505];//dp[k][i][j]表示第k步從左上走到y座標爲i,右下走到y座標爲j
char s[505][505];
int n,m;
int sx,sy,ex,ey,psx,psy,pex,pey;
bool cango(int x,int y){
    if(x<1||x>n||y<1||y>m) return false;
    return true;
}
int main()
{
    rd2(n,m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        cin>>s[i][j];
    int now=0;
    int la=1;//用於滾動dp
    if(s[1][1]==s[n][m]) dp[now][1][m]=1;
    else dp[now][1][m]=0;
    for(int step=1;step<=(n+m-2)/2;step++)//步數
    {
        now^=1;la^=1;
        for(int i=1;i<=m;i++)
            for(int j=1;j<=m;j++)
        {
            sy=i;sx=step-(i-1)+1;
            ey=j;ex=n-(step-(m-j));
            if(!cango(sx,sy)||!cango(ex,ey)) continue;
            dp[now][i][j]=0;
            if(s[sx][sy]!=s[ex][ey]) continue;
            for(int d1=2;d1<=3;d1++)
                for(int d2=0;d2<=1;d2++)
            {
                psx=sx+d[d1][0];psy=sy+d[d1][1];
                pex=ex+d[d2][0];pey=ey+d[d2][1];
                if(!cango(psx,psy)||!cango(pex,pey)||s[psx][psy]!=s[pex][pey]) continue;
                dp[now][i][j]+=dp[la][psy][pey];
                dp[now][i][j]%=mod;
            }
        }
    }
    ll res=0;
    for(int i=1;i<=m;i++)
        res=(res+dp[now][i][i])%mod;
    if((n+m)&1){//如果步數爲偶數,結果是相差1的位置,即dp[now][i][i]和dp[now][i][i+1]
        for(int i=1;i<m;i++)
        res=(res+dp[now][i][i+1])%mod;
    }
    cout<<res<<endl;
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章