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; }