bzoj4098 [Usaco2015 Open]Palindromic Paths dp

由于我比较菜。。虽然看出来是dp模型但是没敢下手= =下手了还错了。。
一开始想的设f[i][j]表示从i走到j所用的方案数,事实证明我丝毫不懂脑子生搬硬套dp式子。。
这题明显跟起点终点毛关系都没有啊。。只跟路径上的字母有关,你这样设连dp方程都列不出来。
设f[i][j][k]表示走i步(一个方向上),左上角的走到了j行,右下角的走到了k行。。
由于n^3太大会爆所以滚动一下。
那么我们根据所走的总步数和j,k很容易推出所在的纵行,那么明显dp会由四种可能转移:左上角出发的只有可能从左边或者上边,右下角出发的只有可能是从右边或者下边,组合一下就好了。
对于dp好的人来说可能这题挺简单的。。

#include
#include
#include
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int N=1e5+5;
const int mo=1e9+7;
int f[2][505][505];
char a[505][505];
typedef long long ll;
ll ans;
int n,m;
int main()
{
    scanf("%d",&n);;
    fo(i,1,n)scanf("%s",a[i]+1);
    f[0][1][n]=1;
    fo(i,1,n)
    {
        fo(x1,1,n)
        if (i-x1+1>=1&&i-x1+1<=n)
        {
            int y1=i-x1+1;
            fo(x2,1,n)
            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])%mo+(f[0][x1][x2]+f[0][x1][x2+1])%mo)%mo;
            }
        }
        fo(x1,1,n)
        fo(x2,1,n)
        {
            f[0][x1][x2]=f[1][x1][x2];
            f[1][x1][x2]=0;
        }
    }
    fo(i,1,n)ans=(ans+f[0][i][i])%mo;
    printf("%d\n",ans);
}

你可能感兴趣的:(bzoj,DP)