Z-Trening_355_z-01paths

假设A,B,C,D分别用0,1,2,3来表示,对于每个位置,前一位置的坐标不是与之相差1就是相差2。本位置坐标为偶数的时候,前一位置为(走路1)本坐标+1或者(走路0)(本坐标+2)%4  > <

假设dp[i][j]表示i长度当前位置为j的一共有多少种,那么要求第k种,我们只需要知道前一位置到底来自于本坐标+1或者(本坐标+2)%4,当然走0路的,是更小的。也就是说确定前一位置来自于哪里,我们只需要用k与dp[i-1][(j+2)%4]比较,小于等于的就走0路,大于的就走1路

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<queue>
using namespace std;
#define LL long long
#define inf 10000000000
#define N 55
#define M 50010
#define eps 1e-8
LL dp[N][4];
int main()
{
  int n,k;
  char r[2];
  /*结束点和起点本是一家亲*/
  while(~scanf("%s%d%d",r,&n,&k))
  {
      int id=r[0]-'A';
      memset(dp,0,sizeof(dp));
      dp[0][id]=1; //结束点在哪里> <,哪里就为1
      for(int i=1;i<=n;++i)
          for(int j=0;j<4;++j)
          {
              if(j&1) dp[i][j]+=dp[i-1][j-1]+dp[i-1][(j+2)%4]; 
              else dp[i][j]+=dp[i-1][j+1]+dp[i-1][(j+2)%4];//真没想到 居然也许会溢出
              //if(dp[i][j]>k) dp[i][j]=k+1; 
          }
          if(dp[n][0]<k) 
          {
              puts("impossible");
              continue;
          }
       int x=n,now=0; //now代表当前坐标
       while(x--)
       {
           if(dp[x][(now+2)%4]>=k) //走0路
           {
               printf("0");
               now=(now+2)%4;
           }
           else //走一路
           {
               printf("1");
               k-=dp[x][(now+2)%4];
               if(now%2) now--;
               else now++;
           }
       }
       printf("\n");
  }
  return 0;
}

 

 

 

posted @ 2013-05-28 22:42  小仪在努力~  阅读(241)  评论(0编辑  收藏  举报