zoukankan      html  css  js  c++  java
  • [USACO15OPEN]回文的路径Palindromic Paths 2.0版

    题目描述

    农夫FJ的农场是一个N*N的正方形矩阵(2le Nle 5002N500),每一块用一个字母作标记。比如说:

    ABCD 
    BXZX 
    CDXB 
    WCBA 

    某一天,FJ从农场的左上角走到右下角,当然啦,每次他只能往右或者往下走一格。FJ把他走过的路径记录下来。现在,请你把他统计一下,所有路径中,回文串的数量(从前往后读和从后往前读一模一样的字符串称为回文串)。

    输入输出格式

    输入格式:

    第一行包括一个整数N,表示农场的大小,接下来输入一个N*N的字母矩阵。

    输出格式:

    Please output the number of distinct palindromic routes Bessie can take,

    modulo 1,000,000,007.

    输出一个整数,表示回文串的数量。

    输入输出样例

    输入样例#1:
    4
    ABCD
    BXZX
    CDXB
    WCBA
    输出样例#1:
    12
    题解:动态规划
    设f[i][j][k]为起点开始竖方向向下走到i,横向走到j,从终点向上走到k,可知l=i+j-k
    f[i][j][k]->f[i+1][j][k]&f[i][j+1][k]&f[i+1][j][k+1]&f[i][j+1][k+1](颜色相同)
    最后答案就是i+j=n时的最大值
    时空间复杂度都是O(n^3)但还有优化
    可以把第一维换成步数,f[i][j][k]表示走i步,向下到i,向上到k
    f[i][j][k]->f[i+1][j+1][k]&f[i+1][j+1][k+1]&f[i+1][j][k+1]&f[i+1][j][k]
    用滚动数组消去一个n
    此题巨坑,时间卡的紧,多谢YZD大佬指点才过
    要点:若f[now][j][k]=0就不转移

    还有一个超级玄学优化,将滚动数组的第一位放到第三维,每次开始前不清空f[][][nxt],改为在i<n时,转移后将
    f[][][now]清空。比原来快1000ms
    
    
     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<iostream>
     5 using namespace std;
     6 typedef long long lol;
     7 int Mod=1000000007;
     8 lol f[501][501][2];
     9 int now,nxt,n,m;
    10 lol ans;
    11 char a[501][501];
    12 void get(int i)
    13 {
    14     int x=0;
    15     char ch=getchar();
    16     while (ch<'A'||ch>'Z') ch=getchar();
    17     while (ch>='A'&&ch<='Z') 
    18     {
    19         x++;
    20         a[i][x]=ch;
    21         ch=getchar();
    22     }
    23 }
    24 int main()
    25 {
    26     register int i,j,k;
    27     //freopen("b.in","r",stdin);
    28     //freopen("b.out","w",stdout);
    29     cin>>n;
    30     m=n;
    31     for (i=1; i<=n; i++)
    32     {
    33         get(i);
    34     }
    35     if (a[1][1]!=a[n][m])
    36     {
    37         cout<<0<<endl;
    38         return 0;
    39     }
    40     f[1][n][0]=1;
    41     now=1;
    42     nxt=0;
    43     for (i=1; i<=n; i++)
    44     {
    45         swap(now,nxt);
    46         for (j=1; j<=i; j++)
    47         {int b=n-i+1;
    48             for (k=n; k>=b; k--)
    49             if(f[j][k][now])
    50             {
    51                 int y1=i-j+1,y2=m-i+n-k+1;
    52                 //printf("%d %d %d %d %d
    ",i,j,y1,k,y2);
    53                 f[j][k][now]%=Mod;
    54                 if (j+1<=n&&k-1>=1&&a[j+1][y1]==a[k-1][y2])
    55                     f[j+1][k-1][nxt]+=f[j][k][now];
    56 
    57                 if (j+1<=n&&y2-1>=1&&a[j+1][y1]==a[k][y2-1])
    58                     f[j+1][k][nxt]+=f[j][k][now];
    59 
    60                 if (y1+1<=m&&k-1>=1&&a[j][y1+1]==a[k-1][y2])
    61                     f[j][k-1][nxt]+=f[j][k][now];
    62 
    63                 if (y1+1<=m&&y2-1>=1&&a[j][y1+1]==a[k][y2-1])
    64                     f[j][k][nxt]+=f[j][k][now];
    65                 if (i<n)
    66                 f[j][k][now]=0;
    67             }
    68         }
    69     }
    70     for (i=1; i<=n; i++)
    71         ans=(ans+f[i][i][now])%Mod;
    72     cout<<ans%Mod;
    73 }
    
    
    
     
  • 相关阅读:
    第2课 C 到 C++ 的升级
    第1课 学习 C++ 的意义
    归并排序
    插入排序与希尔排序
    选择排序
    冒泡排序
    CodeSignal 刷题 —— almostIncreasingSequence
    CodeSignal 刷题 —— matrixElementSum
    Python3 序列解包
    单星号变量(*)和双星号变量(**)的用法
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7265220.html
Copyright © 2011-2022 走看看