zoukankan      html  css  js  c++  java
  • HDU 5617 Jam's maze 巧妙DP

    题意:给你一个字符矩阵,从(1,1)到(n,n)有很多种走法,每一种走法形成一个字符串,问有多少种走法形成的字符串是回文的

    分析:(粘贴BC题解)

    的是回文串,有人会想到后缀数组自动机马拉车什么的,其实只要求方案数很多,所以我们应该想到动态规划,首先是状态的定义,我们可以想着从(1,1)(1,1)(n,n)(n,n)开始走,然后走到相遇。所以我们定义状态可以定义为f[x_1][y_1][x_2][y_2]f[x1​​][y1​​][x2​​][y2​​]表示所对应的两个点(x_1,y_1)(x_2,y_2)(x1​​,y1​​)(x2​​,y2​​),这样的话考虑到数据的范围,显然会爆空间,然后我们想一想就是走多少步和知道x_1,x_2x1​​,x2​​的位置,就可以确定y_1,y_2y1​​,y2​​的位置。于是我们把状态定义为f[i][x_1][x_2]f[i][x1​​][x2​​]即可,状态转移很显然,如果相等的话把四个方向都扫一下即可。因为还是会爆空间,所以我们把第一维改成滚动数组就解决问题

    注:其实这个题解的意思就是从1,1 和n,n 开始按距离  斜着更新,最后统计相遇的地方,相遇显然就是dp[n-1][i][i]

    难点就是斜着更新不好想,还有就是滚动数组的空间优化

    然后附上丑的代码;

    #pragma comment(linker,"/STACK:102400000,102400000")
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <ctime>
    #include <cmath>
    #include <climits>
    #include <iostream>
    #include <algorithm>
    #include <map>
    #include <set>
    #include <stack>
    #include <queue>
    #include <string>
    #include <list>
    #include <bitset>
    #include <vector>
    #include <cassert>
    using namespace std;
    const int maxn=505;
    const int mod=5201314;
    int dp[2][maxn][maxn];
    char s[maxn][maxn];
    int T,n;
    void add(int &x,int y)
    {
        x+=y;
        if(x>mod)x-=mod;
    }
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            for(int i=1;i<=n;++i)
             scanf("%s",s[i]+1);
            if(s[1][1]!=s[n][n])
            {
               printf("0
    ");
               continue;
            }
            int cur=0;
            memset(dp[cur],0,sizeof(dp[cur]));
            dp[cur][1][n]=1;
            for(int i=1;i<n;++i)
            {
              cur^=1;
              memset(dp[cur],0,sizeof(dp[cur]));
              for(int x1=1;x1<=i+1;++x1)
              {
                 for(int x2=n;x2>=n-i;--x2)
                 {
                      int y1=i+2-x1;
                      int y2=n*2-x2-i;
                      if(s[x1][y1]!=s[x2][y2])continue;
                      add(dp[cur][x1][x2],dp[cur^1][x1][x2]);
                      add(dp[cur][x1][x2],dp[cur^1][x1][x2+1]);
                      add(dp[cur][x1][x2],dp[cur^1][x1-1][x2]);
                      add(dp[cur][x1][x2],dp[cur^1][x1-1][x2+1]);
                 }
              }
            }
            int ans=0;
            for(int i=1;i<=n;++i)
              add(ans,dp[cur][i][i]);
           printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    vba create rectangle 矩形
    (zz)nnotation学习笔记2:关于Annotation与符号,还是要读arcmap帮助!!!
    backgroundworker
    C# , mongodb ,study
    工作中常用的dos命令 数据处理经验总结
    你需要明白的SQL SERVER书签查找(Bookmark Lookup)
    使用CalendarExtender
    js控制5秒后页面自动跳转
    HTML按秒数的页面跳转
    序列化与反序列化读取保存xml文件
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5177293.html
Copyright © 2011-2022 走看看