51Nod-1503-猪和回文

来源:互联网 发布:vmware 端口转发 ssh 编辑:程序博客网 时间:2024/05/12 23:48

ACM模版

描述

描述

题解

万万没想到,这是CF div.2 E题,在51才放在了4级算法,这个世界真奇妙,某大牛说的有趣:难道是通货膨胀的厉害?

很好地一道dp题,很无奈,我不会,是参考他人思路写的,很强势!!!

一开始想到了dp,也想到了从两端向中间查找,但是细部的处理没有想到合适的手段,还是道行浅,
于是看了一个道行深的思路:
一个点走,相当于两个点分别从(1,1)向下向右走,另一个从(N,M)向上向左走,并且这两个点走的字符必须相同,dp[step][x_1][y_1][x_2][y_2]表示走step步,两个点分别到达(x_1,y_1),(x_2,y_2)这两个点并且路径上的字符相同的方案数有多少,那么每次按照他们能走的方向递推就行了。
还有个问题这样的dp数组是开不下的,首先可以把它写成滚动数组,然后,因为知道起点,步数还有x坐标,y坐标是可以计算出来的,所以可以把y坐标的两维省掉。
于是就是枚举步数和两个x坐标了,还有点需要注意的就是N+M是奇数的时候。

代码

#include <stdio.h>const int MAXN = 5e2 + 5;const int MOD = 1e9 + 7;int N, M;int dp[2][MAXN][MAXN];  //  枚举两个点x坐标char s[MAXN][MAXN];void add(int &x, int y){    x += y;    if (x >= MOD)    {        x -= MOD;    }}int main(){    scanf("%d%d", &N, &M);    for (int i = 1; i <= N; i++)    {        scanf("%s", s[i] + 1);    }    int cur = 0;    dp[0][1][N] = (s[1][1] == s[N][M]);    for (int step = 1; step <= (M + N - 2) / 2; step++)    {        cur ^= 1;        for (int i = 0; i <= N; i++)        {            for (int j = 1; j <= N; j++)            {                dp[cur][i][j] = 0;            }        }        for (int x_1 = 1; x_1 <= N && x_1 - 1 <= step; x_1++)        {            for (int x_2 = N; x_2 >= 1 && N - x_2 <= step; x_2--)            {                int y_1 = 1 + step - (x_1 - 1);                int y_2 = M - (step - (N - x_2));                if (s[x_1][y_1] != s[x_2][y_2])                {                    continue;                }                //  ⬇️⬆️                add(dp[cur][x_1][x_2], dp[cur ^ 1][x_1][x_2]);                //  ⬇️⬅️                add(dp[cur][x_1][x_2], dp[cur ^ 1][x_1][x_2 + 1]);                //  ➡️⬆️                add(dp[cur][x_1][x_2], dp[cur ^ 1][x_1 - 1][x_2]);                //  ➡️⬅️                add(dp[cur][x_1][x_2], dp[cur ^ 1][x_1 - 1][x_2 + 1]);            }        }    }    int ans = 0;    //  累计两个点x坐标都到同一位置的情况    for (int i = 1; i <= N; i++)    {        add(ans, dp[cur][i][i]);    }    if ((N + M) % 2)    //  如果步数为奇数    {        for (int i = 1; i < N; i++)        {            add(ans, dp[cur][i][i + 1]);        }    }    printf("%d\n", ans);    return 0;}
1 0
原创粉丝点击