zoukankan      html  css  js  c++  java
  • LOJ 2550 「JSOI2018」机器人——找规律+DP

    题目:https://loj.ac/problem/2550

    只会写20分的搜索……

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=5;
    int n,m,ans;
    bool b[N][N],vis[N][N];
    void dfs(int x,int y,bool fx,int lj)
    {
        if(y>m)y=1; if(x>n)x=1;
        if(vis[x][y])
        {
            if(x==1&&y==1)
            {
                bool fg=0;
                for(int i=1;i<=n;i++)
                    for(int j=1;j<=m;j++)
                        if(!vis[i][j]){fg=1;break;}
                if(!fg)ans+=lj;
            }
            return;
        }
        if(b[x][y])fx=1; if(!fx)lj++;
        vis[x][y]=1;
        dfs(x+1,y,fx,lj); dfs(x,y+1,fx,lj);
        vis[x][y]=0;
    }
    int main()
    {
        int T;scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                    scanf("%1d",&b[i][j]);
            ans=0;
            dfs(1,1,0,0);
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    观察多篇题解:

    https://blog.csdn.net/qq_39972971/article/details/80441415

    https://www.cnblogs.com/cjyyb/p/10422074.html

    https://blog.csdn.net/scar_lyw/article/details/80411617

    由结论可知合法的方案取决于左上角 d*d 怎么决策。(副对角线可以拐,所以是 d 条而不是 2*d-1 条)

    枚举 d*d 里向下 i 步,向右 j=d-i 步,那么需要 i 和 n 互质、 j 和 m 互质。这样就是合法方案。考虑已知 i , j ,算贡献。

    每个位置 ( x, y ) 都会在 “一轮”(d步) 之后走到 ( x+i , y+j ) 。

    ( 1, 1 ) 位置第一轮走到 ( i+1 , j+1 ) 。考虑 DP 这个第一轮的走法,就知道全局的走法了。

    ( 1, 1 ) 只能向下走或向右走。走过位置 ( x, y ) ,意味着会在之后的轮中把 ( x+k*i , y+k*j ) 都走过。

    把 “走到第一个障碍为止的步数” 改成 “走到每个障碍为止的步数中的最小值” , 一个位置 ( x, y ) 的权值就是所有 ( x+k*i , y+k*j ) 的是障碍的点的 “走到该点的步数最小值” 取 min ; 

    就是要 DP 一条从 ( 1, 1 ) 到 ( i+1 , j+1 ) 的只能向下或向右走的路径,该路径贡献是路径上各点权值的最小值。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    int Mn(int a,int b){return a<b?a:b;}
    int gcd(int a,int b){return b?gcd(b,a%b):a;}
    const int N=55,M=N*N,mod=998244353;
    int upt(int x){while(x>=mod)x-=mod;while(x<0)x+=mod;return x;}
    
    int n,m,lm,c[N][N],dp[N][N][M],ans;
    bool b[N][N];
    void cz(int &x,int y){x=upt(x+y);}
    void solve(int x,int y)
    {
      memset(dp,0,sizeof dp);
      dp[1][1][c[1][1]]=1;
      for(int i=1;i<=x+1;i++)
        for(int j=1;j<=y+1;j++)
          for(int k=0;k<=lm;k++)
        {
          int tp=dp[i][j][k]; if(!tp)continue;
          if(i<=x)cz(dp[i+1][j][Mn(k,c[i+1][j])],tp);
          if(j<=y)cz(dp[i][j+1][Mn(k,c[i][j+1])],tp);
        }
      for(int k=1;k<=lm;k++)
        ans=(ans+(ll)k*dp[x+1][y+1][k])%mod;
    }
    int main()
    {
      int T;scanf("%d",&T);
      while(T--)
        {
          ans=0;
          scanf("%d%d",&n,&m); lm=n*m;
          for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
          scanf("%1d",&b[i][j]);
          int g=gcd(n,m);
          for(int x=1;x<g;x++)
        {
          int y=g-x;
          if(gcd(x,n)!=1||gcd(y,m)!=1)continue;
          for(int i=1;i<=x+1;i++)
            for(int j=1;j<=y+1;j++)
              {
            int d=i+j-2;
            if(b[i][j]){c[i][j]=d;continue;}
            int tx=i+x, ty=j+y; d+=g;
            if(tx>n)tx-=n; if(ty>m)ty-=m;
            while(1)
              {
                if(b[tx][ty]||(tx==i&&ty==j))
                  {c[i][j]=d;break;}
                tx+=x; ty+=y; d+=g;
                if(tx>n)tx-=n;if(ty>m)ty-=m;
              }
              }
          solve(x,y);
        }
          printf("%d
    ",ans);
        }
      return 0;
    }
  • 相关阅读:
    第3次作业卷积神经网络
    SpringCloud Sidecar 整合.Net WebApi
    redefinition of class解决
    DP学习笔记
    NOIP2018 Day2毒瘤题目
    NOIP Day1总结
    关于DP
    这次的PION的总结
    NOIP模拟赛D2T1自己的解题思路
    ABAP Editor自动完成功能
  • 原文地址:https://www.cnblogs.com/Narh/p/10768502.html
Copyright © 2011-2022 走看看