zoukankan      html  css  js  c++  java
  • 51nod-1503 猪和回文

    题目链接

    一只猪走进了一个森林。很凑巧的是,这个森林的形状是长方形的,有n行,m列组成。我们把这个长方形的行从上到下标记为1到n,列从左到右标记为1到m。处于第r行第c列的格子用(r,c)表示。

    刚开始的时候猪站在(1,1),他的目标是走到(n,m)。由于猪回家心切,他在(r,c)的时候,只会往(r+1,c)或(r,c+1)走。他不能走出这个森林。

    这只猪所在的森林是一个非同寻常的森林。有一些格子看起来非常相似,而有一些相差非常巨大。猪在行走的过程中喜欢拍下他经过的每一个格子的照片。一条路径被认为是漂亮的当且仅当拍下来的照片序列顺着看和反着看是一样的。也就是说,猪经过的路径要构成一个回文。

    数一数从(1,1)到(n,m)有多少条漂亮路径。答案可能非常巨大,请输出对 109+7 取余后的结果。

    样例解释:有三种可能

      

    Input
    单组测试数据。
    第一行有两个整数 n,m (1≤n,m≤500),表示森林的长和宽。
    接下来有n行,每行有m个小写字母,表示每一个格子的类型。同一种类型用同一个字母表示,不同的类型用不同的字母表示。

    -----------------------------------------------------------------------------------------------------------------------------------------------

    dp(i,j,x,y)代表从(i,j)到(x,y)的路径数则:

    dp(i,j,x,y) =  { char(i,j)==char(x,y) ? [dp(i+1,j,x-1,y)+dp(i+1,j,x,y-1)+dp(i,j+1,x-1,y)+dp(i,j+1,x,y-1)] : 0;}

    (i,j) 位于上三角,(x,y)位于下三角。从中间分界线向两个顶点处转移。

    时间复杂度为N^3,因为状态转移只与上一次的状态相关,所以开两个N*N的数组即可。

    #define  _CRT_SECURE_NO_WARNINGS
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int N = 512;
    const int MOD = 1e9 + 7;
    typedef long long LL;
    typedef pair<int, int> int2;
    
    LL dp[2][N][N];
    char maze[N][N];
    int n, m, dim;
    int level;
    int2 coordu, coordl;
    bool flag = true;
    inline int Cnt(){ return std::min(dim, level + 1); }
    char upper(int id){
        coordu.first = (level<n) ? (level - id) : (n - 1 - id);
        coordu.second = level - coordu.first;
        return maze[coordu.first][coordu.second];
    }
    char lower(int id){
        coordl.second = (level < m) ? (m - 1 - level+id) : id;
        coordl.first = m + n - 2 - level - coordl.second;
        return maze[coordl.first][coordl.second];
    }
    int packu(){
        if (coordu.first + 1 >= n) return -1;
        return ((level + 1<n) ? (level + 1) : (n - 1)) - coordu.first - 1;
    }
    int packl(){
        if (coordl.second - 1<0) return -1;
        return coordl.second - 1 - ((level + 1<m) ? (m - 1 - level - 1) : (0));
    }
    int main(){
        cin >> n >> m; dim = std::min(m, n);
        for (int i = 0; i<n; i++) scanf("%s", maze[i]);
        memset(dp, 0, sizeof(dp));
    
        level = (m + n) / 2 - 1;
        bool ismid = true;
        while (level >= 0){
            flag = !flag;
            int maxc = Cnt();
            for (int i = 0; i<maxc; i++) for (int j = 0; j<maxc; j++){
                char cu = upper(i);
                char cl = lower(j);
                if (cu == cl){
                    if (ismid) dp[flag][i][j] = ((coordu.first == coordl.first) || (coordu.second == coordl.second));
                    else{
                        int ii = packu(); int jj = packl();
                        dp[flag][i][j] = 0;
                        if (ii >= 0 && jj >= 0)   dp[flag][i][j] += dp[!flag][ii][jj];
                        if (ii + 1 >= 0 && jj >= 0) dp[flag][i][j] += dp[!flag][ii + 1][jj];
                        if (ii >= 0 && jj + 1 >= 0) dp[flag][i][j] += dp[!flag][ii][jj + 1];
                        dp[flag][i][j] += dp[!flag][ii + 1][jj + 1];
                        dp[flag][i][j] %= MOD;
                    }
                }
                else dp[flag][i][j] = 0;
            }
            level--; ismid = false;
        }
        std::cout << dp[flag][0][0] << endl;
        return 0;
    }
  • 相关阅读:
    Cross-Site Scripting XSS 跨站攻击全攻略 分类: 系统架构 2015-07-08 12:25 21人阅读 评论(2) 收藏
    WAS集群:记一次Node Agent不活动问题解决过程
    Oracle RAC集群资料收集
    Linux使用 tar命令-g参数进行增量+差异备份、还原文件
    WAS7.0安装补丁升级程序无法替换文件 java/docs/autorun.inf解决办法
    Java程序员面试失败的5大原因
    Lemon OA第4篇:常用功能
    Lemon OA第3篇:核心功能
    Lemon OA第2篇:功能解析方法
    Activiti5小试牛刀demo流程
  • 原文地址:https://www.cnblogs.com/redips-l/p/7999010.html
Copyright © 2011-2022 走看看