bzoj 4098 [Usaco2015 Open]Palindromic Paths

Description

Farmer John's farm is in the shape of an N×N grid of fields (1≤N≤500), each labeled with a letter in the alphabet. For example:
ABCD
BXZX
CDXB
WCBA
Each day, Bessie the cow walks from the upper-left field to the lower-right field, each step taking her either one field to the right or one field downward. Bessie keeps track of the string that she generates during this process, built from the letters she walks across. She gets very disoriented, however, if this string is a palindrome (reading the same forward as backward), since she gets confused about which direction she had walked.
Please help Bessie determine the number of distinct routes she can take that correspond to palindromes. Different ways of obtaining the same palindrome count multiple times. Please print your answer modulo 1,000,000,007.
从n×n 的矩阵 左上角走到右下角会有一个长度 n+n+1的字符串,问有多少种走法使得路径字符串为回文?

Input

The first line of input contains N, and the remaining N lines contain the N rows of the grid of fields. Each row contains N characters that are in the range A..Z.

Output

Please output the number of distinct palindromic routes Bessie can take, modulo 1,000,000,007.

Sample Input

4
ABCD
BXZX
CDXB
WCBA

Sample Output

12
Bessie can make the following palindromes
1 x "ABCDCBA"
1 x "ABCWCBA"
6 x "ABXZXBA"
4 x "ABXDXBA"

noip传纸条的升级版

我们设它是从(1,1)和(n,n)分别出发的,f[i][j][k]表示走了i步,上面走到第j行,下面走到第k行(各自的列可以用表达式算出,有规律的)

但是我们发现n^3的空间开不下,于是改滚动

然后答案就是走了n步后每个f[0][i][i]的和

另外注意,f数组不能开long long,int足矣,把空间开大反而会使时间变慢TLE

#include<cstdio>
#include<iostream>
using namespace std;
const int M=1000000007;
char a[505][505];
int f[2][505][505];
int n;
long long ans;
int main()
{
    cin>>n;
    ans=0;
    for(int i=1;i<=n;i++) scanf("%s",a[i]+1);
    f[0][1][n]=1;
    for(int i=1;i<=n;i++)
    {
        for(int x1=1;x1<=n;x1++)
        if(i+1-x1>=1&&i+1-x1<=n)
        {
            int y1=i+1-x1;
            for(int x2=1;x2<=n;x2++)
            if((n+1)*2-x1-y1-x2>=1&&(n+1)*2-x1-y1-x2<=n)
            {
                int y2=(n+1)*2-x1-y1-x2;
                if(a[x1][y1]==a[x2][y2])
                f[1][x1][x2]=((f[0][x1-1][x2]+f[0][x1-1][x2+1])%M+(f[0][x1][x2]+f[0][x1][x2+1])%M)%M;
            }
        }
        for(int x1=1;x1<=n;x1++)
        for(int x2=1;x2<=n;x2++)
        {
            f[0][x1][x2]=f[1][x1][x2];
            f[1][x1][x2]=0;
        }
    }
    for(int i=1;i<=n;i++) ans=(ans+f[0][i][i])%M;
    cout<<ans<<endl;
    return 0;
}
				







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值