NOJ [1409] 鼹鼠鼹鼠你不出来,noj


  • 问题描述
  • 一只鼹鼠想要探索北方的一块草地,这块草地是一个无限大的方格矩阵,由于地鼠只会往前不会后退,所以他只会朝北或者东、西方向刨。由于刨过的地方已不是土地,所以不会再次进入这个方格。现在这只鼹鼠打算刨n步,它想要知道能有多少种刨的方案,你能帮他算算吗?注:只要有任何的不同,就算是不同的刨法。

    思考:每次走一步,衍生出的新状态是怎么样的?
     请看图1:走一步产生的状态         ,向北的有1个,其他的有两个

       NOJ [1409] 鼹鼠鼹鼠你不出来,noj_第1张图片
    请看图2:走两步的状态   ,向北的有3个,其他的有4个
    NOJ [1409] 鼹鼠鼹鼠你不出来,noj_第2张图片

    显然可以发现,从1步的状态转到2步的状态,原来向北的,向东的,向西的,分别产生了一个向北的,原来向北的,向东的,分别产生了一个向东的,原来向北的,向西的,分别产生一个向西的,

    我们设a为当前向北的个数,b为其他的个数
    由此推广到一般形式
    newa=a+b;
    newb=2*a+b;
    cnt=3*a+2*b;

    理解了这个以后,就能写代码了,不过请注意,由于一次次的更新以后,数据会很大,甚至__int64, double 都不能存下来
    所以只能用大数模拟


    #include<stdio.h>
    #include<string.h>
    
       int dp[120][120];
    int main()
    {
       int  a[120],b[120],t[120],r[120],s[120];
      int i,n;
      memset(dp,0,sizeof(dp));
      memset(a,0,sizeof(a));
      memset(b,0,sizeof(b));
      a[1]=1;
      b[1]=2;
      dp[1][1]=3;
      int j,k;
      for(i=2;i<=100;i++)
      {
        memset(r,0,sizeof(r));
        memset(s,0,sizeof(s));
        for(k=1;k<120;k++)
        {
            r[k]+=a[k]*3;
            if(r[k]>=10)
            {
            r[k+1]+=r[k]/10;
            r[k]%=10;
            }
            s[k]+=b[k]*2;
            if(s[k]>=10)
            {
            s[k+1]+=s[k]/10;
            s[k]%=10;
            }
        }
        for(j=1;j<120;j++)
        {
          
          dp[i][j]+=r[j]+s[j];
          if (dp[i][j]>=10)
          {
            dp[i][j+1]=dp[i][j]/10;
            dp[i][j]%=10;
          }
        }
        memset(t,0,sizeof(t));
        int c=0,d=0;
        for(k=1;k<120;k++)
        {
          t[k]=a[k];
          a[k]=0;
          a[k]=t[k]+b[k]+c;
          if(a[k]>=10)
          {
            c=a[k]/10;
            a[k]%=10;
          }
          else
            c=0;
        }
        for(k=1;k<=100;k++)
        {
          b[k]+=2*t[k];
          if(b[k]>=10)
          {
            b[k+1]+=b[k]/10;
            b[k]%=10;
          }
        }
      }
      while(~scanf("%d",&n))
      {
        for(i=100;i>0;i--)
           if(dp[n][i]!=0)
              break;
        for(j=i;j>=1;j--)
           printf("%d", dp[n][j]);
         printf("\n");
      }
      return 0;
    }
    

    这个题可以训练大数模拟,希望对大数模拟还不熟悉的同学来说,这篇文章能有用。











你可能感兴趣的:(NOJ [1409] 鼹鼠鼹鼠你不出来,noj)