/*
* 方法一:深度优先搜索
* 该方法会超时,迭代次数过多。
*
*/
void get(int x, int y, int arr[4][3], int left, int *cnt){
if(x<0 || x>=4 || y<0 || y>=3 || arr[x][y]) return;
if(left == 0){
(*cnt)++;
return;
}
left--;
get(x+1, y+2, arr, left, cnt);
get(x+1, y-2, arr, left, cnt);
get(x-1, y+2, arr, left, cnt);
get(x-1, y-2, arr, left, cnt);
get(x+2, y+1, arr, left, cnt);
get(x+2, y-1, arr, left, cnt);
get(x-2, y+1, arr, left, cnt);
get(x-2, y-1, arr, left, cnt);
}
int knightDialer(int n){
int arr[4][3];
int cnt = 0, i, j, tmp;
memset(arr, 0, sizeof(arr));
arr[3][0] = 1;
arr[3][2] = 1;
for(i=0; i<4; i++){
for(j=0; j<3; j++){
if(arr[i][j]) continue;
tmp = 0;
get(i, j, arr, n-1, &tmp);
cnt += tmp;
if(cnt >= 1000000007) cnt -=1000000007;
}
}
return cnt;
}
/*
* 方法二:动态规划
* 维护一个与号码对应的二维数组,与号码对应的位置元素值表示到当前位置有几种方式;
* 当n==1时,需要一步走到该位置,则号码对应的位置都为1,因此都有一种方法可以到达该位置。
* 当n==2时,需要两步走到该位置,号码对应位置的值为n==1可以走到的位置的对应值相加,有两个。
* 当n==3时,同理可根据,n==2时的值递推得到。
*/
#define Max 1000000007
unsigned long long value(unsigned long long x){
while(x>=Max)
x -= Max;
return x;
}
int knight(n){
unsigned long long arr[4][3], i, j, cnt=0;
unsigned long long arr_tmp[4][3];
unsigned long long tmp;
memset(arr, 0, sizeof(arr));
for(i=0; i<4; i++){
for(j=0; j<3; j++){
arr[i][j] = 1;
}
}
arr[3][0] = 0;
arr[3][2] = 0;
for(i=0; i<n-1; i++){
memset(arr_tmp, 0, sizeof(arr));
arr_tmp[0][0] = value(arr[1][2] + arr[2][1]);
arr_tmp[0][1] = value(arr[2][2] + arr[2][0]);
arr_tmp[0][2] = value(arr[1][0] + arr[2][1]);
arr_tmp[1][0] = value(arr[0][2] + arr[2][2] + arr[3][1]);
arr_tmp[1][2] = value(arr[2][0] + arr[3][1] + arr[0][0]);
arr_tmp[1][1] = 0;
arr_tmp[2][0] = value(arr[0][1] + arr[1][2]);
arr_tmp[2][1] = value(arr[0][0] + arr[0][2]);
arr_tmp[2][2] = value(arr[0][1] + arr[1][0]);
arr_tmp[3][1] = value(arr[1][0] + arr[1][2]);
memcpy(arr, arr_tmp, sizeof(arr));
}
for(i=0; i<4; i++){
for(j=0; j<3; j++){
cnt += arr[i][j];
cnt = value(cnt);
}
}
return cnt;
}
int knightDialer(int n){
return knight(n);
}