zoukankan      html  css  js  c++  java
  • CodeForces

    题目:给出一个字母矩阵,问从左上角走到右下角的走法有多少种走法能走出回文子串,只能向下或向右走。

    思路:正解是O(n^3)的dp,也跑了2.9s,可见这题时限是比较紧的。自然的一个想法是两头同时向中间走,这样可以保证走出的是回文串,问题在于如何dp。一共需要走O(n+m)步,而每一步从左上走过来的和右下走过来的进行匹配,以行数作为下标表示二者即可(因为距离确定的情况下只需要知道一个坐标)。所以dp[i][j][k]就表示在第i步,第j行和第k行配对组成的回文串的数目,滚动数组优化空间把步数那一维去掉。转移的时候需要考虑四种走法(对应两头的两种走法相乘)。然后就是递推到中间之后,根据x和y轴的长度之和还需要稍微讨论一下。

    #include <bits/stdc++.h>
    #define pb push_back
    #define se second
    #define fs first
    #define sq(x) (x)*(x)
    #define eps 0.000000001
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    const ll mod=1e9+7;
    const int maxv=505;
    ll dp[2][maxv][maxv];
    int n,m;
    char r[maxv];
    char mp[maxv][maxv];
    const int d1[2]={1,0};
    const int d2[2]={0,1};
    const int p1[2]={-1,0};
    const int p2[2]={0,-1};
    bool out(int x,int y){
        return x<0||x>=n||y<0||y>=m;
    }
    int main(){
    //    freopen("/home/files/CppFiles/in","r",stdin);
        cin>>n>>m;
        for(int i=0;i<n;i++){
            scanf("%s",r);
            for(int j=0;j<m;j++){
                mp[i][j]=r[j];
            }
        }
        if(mp[0][0]!=mp[n-1][m-1]){
            cout<<0<<endl;
            return 0;
        }
        bool f=1;
        dp[0][0][n-1]=1;
        bool bbb=1;
        for(int d=0;d<(n+m-2)/2;d++){
            f^=1;
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++){
                    dp[f^1][i][j]=0;
                }
            }
            for(int i=0;i<n;i++){///up
                for(int j=0;j<n;j++){///down
                    int x1=i,y1=d-x1;
                    int x2=j,y2=n+m-2-d-x2;
                    if(out(x1,y1)||out(x2,y2))  continue;
                    for(int p=0;p<2;p++){
                        for(int q=0;q<2;q++){
                            int dx1=x1+d1[p],dy1=y1+d2[p];
                            int dx2=x2+p1[q],dy2=y2+p2[q];
                            if(out(dx1,dy1)||out(dx2,dy2)) continue;
                            if(mp[dx1][dy1]==mp[dx2][dy2]){
                                dp[f^1][dx1][dx2]=(dp[f^1][dx1][dx2]+dp[f][x1][x2])%mod;
                            }
                        }
                    }
                }
            }
            ll ans=0;
            for(int i=0;i<n;i++){
                if(i+1<n&&(n+m)%2==1)
                    ans=(ans+dp[f^1][i][i+1])%mod;
                ans=(ans+dp[f^1][i][i])%mod;
            }
            cout<<ans<<endl;
            return 0;
        }
    }
    View Code
  • 相关阅读:
    18.12.30 【sssx】Trie图
    18.12.30 【sssx】线段树
    18.12.25 POJ 1039 Pipe
    18.12.25 POJ 3525 Most Distant Point from the Sea(半平面+二分)
    18.12.25 POJ 1228 Grandpa's Estate
    18.12.22 luogu P3047 [USACO12FEB]附近的牛Nearby Cows
    18.12.21 DSA 中缀表达式的值
    18.12.21 luogu P3650 [USACO1.3]滑雪课程设计Ski Course Design
    18.12.21 【USACO】Times17
    18.12.20 DSA Full Tank?(DP+BFS)
  • 原文地址:https://www.cnblogs.com/Cw-trip/p/4730449.html
Copyright © 2011-2022 走看看