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

108 篇文章 0 订阅

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 ofn 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.


题意,给出一个矩阵,要求找出从1,1 - n -1,m-1的回文路径数。每个点只能向右下方走一步。

由于是回文路,所以可以直接枚举两个端点。很容易可以得到一个方程dp[x1][x2][y1][y2] = sum[dp[相邻的四个点]},这里,是空间时间都是四维的,会爆。必须要减一维,我们可以发现,x1 x2 y1 y2之间是有关系的,利用这个关系可以使复杂度降一维。如果当前走了step步,且得到x1,y1那么直接可以推出y1 = step - x1,y2 = m + n - 2 - step - x2;这样就可以减少一维了,或者给出x1 y1 x2也可以直接推出y2,这里用step的方法,是为了进一步减空间复杂度。因为,dp推直接用步数从小到大,所以可以用滚动数组,只存当前步与上一步的状态,进行转移。转移就是左上方的点,向上向左,右下方的点,向右向下进行状态转移就可以了。所以空间复杂度就是o(n * n ),时间复杂度为o(n * n * n );状态初始化的时候,要注意,边界控制有有效的才可以。

#define N 501
#define M 100005
#define maxn 205
#define MOD 1000000007
int n,m,dp[2][N][N];
char land[N][N];
bool isRight(int x,int y){
    if(x >= 0 && x < n && y >=0 && y< m) return true;
    return false;
}
void update(int & x,int y){
    x += y;x%= MOD;
}
void Add(int x1,int y1,int x2,int y2,int px1,int px2,int flag){
    if(isRight(x1,y1)&& isRight(x2,y2) && land[x1][y1] == land[x2][y2])
        update(dp[flag^1][x1][x2],dp[flag][px1][px2]);
}
int main()
{
    while(S2(n,m)!=EOF)
    {
        FI(n){
            SS(land[i]);
        }
        int flag = 0,sn = (n + m - 2) / 2;
        fill(dp,0);
        FI(n) for(int j = i;j<n;j++) {
            int x1 = i,x2 = j,y1 = sn - x1,y2 = m + n - 2 - sn - x2;
            if(isRight(x1,y1) && isRight(x2,y2) && abs(x1 - x2) + abs(y1 - y2) <= 1){
                dp[flag][i][j] = (land[x1][y1] == land[x2][y2] )? 1 : 0;
            }
        }
        for(int step = sn;step >=1;step--,flag = flag^1){
            fill(dp[flag^1],0);
            FI(n) for(int j = i;j<n;j++){
                int x1 = i,x2 = j,y1 = step - x1,y2 = m + n - 2 - step - x2;
                Add(x1    ,y1 - 1,x2    ,y2 + 1,x1,x2,flag);
                Add(x1    ,y1 - 1,x2 + 1,y2    ,x1,x2,flag);
                Add(x1 - 1,y1    ,x2    ,y2 + 1,x1,x2,flag);
                Add(x1 - 1,y1    ,x2 + 1,y2    ,x1,x2,flag);
            }
        }
        printf("%d\n",dp[flag][0][n-1]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值