51nod 1503 猪和回文(dp滚存)

题面

大意:在一个n*m的矩形中从(1,1)走到(n,m)而且走过的路径是一条回文串,统计方案数

 

sol:我们考虑从(1,1)和(n,m)两端开始算,这样就只要保证每次经过的字符一样就可以满足回文了,因为一定有一个循环需要枚举步数,知道了步数自然只要知道了x坐标就可以算出y坐标了,于是只要枚举x1和x2了,因为当前这步一定是从上一步转移过来的,就可以滚存了

 

#include<bits/stdc++.h>
using namespace std;
#define Mod 1000000007
long long n, m, f[2][505][505], ans = 0;
char Map[505][505];
inline void Add(long long &x, long long y){x = (x + y) % Mod;}
int main()
{
    freopen("51nod1503.in","r",stdin);
    while(~scanf("%lld%lld", &n, &m))
    {
        ans = 0;
        for(long long i = 1; i <= n; i++)
            scanf("%s", Map[i] + 1);
        if(Map[1][1] != Map[n][m])
        {
            printf("0\n");
            continue;
        }
        long long cur = 0;
        f[cur][1][n] = 1;
        for(long long step = 1; step <= (n + m - 2) / 2; step++)
        {
            cur ^= 1;
            for(long long i = 1; i <= n; i++)
            for(long long j = 1; j <= n; j++)
                f[cur][i][j] = 0;
            for(long long x1 = 1; x1 <= n && x1 - 1 <= step; x1++)
            for(long long x2 = n; x2 >= 1 && n - x2 <= step; x2--)
            {
                long long y1 = 1 + (step - (x1 - 1));
                long long y2 = m - (step - (n - x2));
                if (Map[x1][y1] != Map[x2][y2]) continue;
                Add(f[cur][x1][x2], f[cur ^ 1][x1 - 1][x2 + 1]);
                Add(f[cur][x1][x2], f[cur ^ 1][x1 - 1][x2]);
                Add(f[cur][x1][x2], f[cur ^ 1][x1][x2 + 1]);
                Add(f[cur][x1][x2], f[cur ^ 1][x1][x2]);
            }
        }
        for(long long i = 1; i <= n; i++)
            Add(ans, f[cur][i][i]);
        if((n + m) & 1)
        for(long long i = 1; i < n; i++)
            Add(ans, f[cur][i][i + 1]);
        printf("%lld\n", ans);
    }
}
View Code

 

posted @ 2018-08-08 20:36  yccdu  阅读(111)  评论(0编辑  收藏  举报