Simplified Chess Engine


Problem Statement :


Chess is a very popular game played by hundreds of millions of people. Nowadays, we have chess engines such as Stockfish and Komodo to help us analyze games. These engines are very powerful pieces of well-developed software that use intelligent ideas and algorithms to analyze positions and sequences of moves, as well as find tactical ideas. Consider the following simplified version of chess:

Board: It's played on a  board between two players named Black and White.
Pieces and Movement:
White initially has  pieces and Black initially has  pieces.
There are no Kings and no Pawns on the board. Each player has exactly one Queen, at most two Rooks, and at most two minor pieces (i.e., a Bishop and/or Knight).
Each piece's possible moves are the same as in classical chess, and each move made by any player counts as a single move.
There is no draw when positions are repeated as there is in classical chess.
Objective: The goal of the game is to capture the opponent’s Queen without losing your own.
Given  and the layout of pieces for  games of simplified chess, implement a very basic (in comparison to the real ones) engine for our simplified version of chess with the ability to determine whether or not White can win in  moves (regardless of how Black plays) if White always moves first. For each game, print YES on a new line if White can win under the specified conditions; otherwise, print NO.

Input Format

The first line contains a single integer, , denoting the number of simplified chess games. The subsequent lines define each game in the following format:

The first line contains three space-separated integers denoting the respective values of  (the number of White pieces),  (the number of Black pieces), and  (the maximum number of moves we want to know if White can win in).
The  subsequent lines describe each chesspiece in the format t c r, where  is a character  denoting the type of piece (where  is Queen,  is Knight,  is Bishop, and  is Rook), and  and  denote the respective column and row on the board where the figure is placed (where  and ). These inputs are given as follows:
Each of the  subsequent lines denotes the type and location of a White piece on the board.
Each of the  subsequent lines denotes the type and location of a Black piece on the board.
Constraints

It is guaranteed that the locations of all pieces given as input are distinct.
Each player initially has exactly one Queen, at most two Rooks and at most two minor pieces.


Output Format

For each of the  games of simplified chess, print whether or not White can win in  moves on a new line. If it's possible, print YES; otherwise, print NO.



Solution :



title-img


                            Solution in C :

In  C  :






#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef struct State State;

typedef struct {
    State **data;
    int count;
    int capacity;
} List;

List *list_create(int capacity) {
    List *list = (List *)malloc(sizeof(List));
    list->capacity = (capacity > 0) ? capacity : 8;
    list->count = 0;    
    list->data = (State **)malloc(list->capacity*sizeof(State *));
    assert(list->data);
    return list;
}

void list_destroy(List *list) {
    if (list && list->data) {
        for (int i = 0; i < list->count; i++) free(list->data[i]);
        free(list->data);
    }
    free(list);
}
        
void list_append(List *list, State *item) {
    if (list->count >= list->capacity) {
        list->capacity = 1.5*list->capacity + 1;
        list->data = (State **)realloc(list->data, list->capacity*sizeof(State *));
        assert(list->data);
    }
    list->data[list->count++] = item;
}

/**********************************************************************/

#define TURN_WHITE 0
#define TURN_BLACK 1

#define PIECE_NONE 0

#define COLOR_MASK   0xf0

#define PIECE_MASK   0x0f
#define QUEEN  0x01
#define ROOK   0x02
#define BISHOP 0x03
#define KNIGHT 0x04

#define COLOR_WHITE  0x10
#define WHITE_QUEEN  0x11
#define WHITE_ROOK   0x12
#define WHITE_BISHOP 0x13
#define WHITE_KNIGHT 0x14

#define COLOR_BLACK  0x20
#define BLACK_QUEEN  0x21
#define BLACK_ROOK   0x22
#define BLACK_BISHOP 0x23
#define BLACK_KNIGHT 0x24

struct State {
    char turn;
    unsigned char board[4][4];
};

State *state_new(void) {
    State *s = (State *)malloc(sizeof(State));
    s->turn = 0;
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            s->board[i][j] = PIECE_NONE;
        }
    }
    return s;
}

State *state_copy(State *orig) {
    State *copy = (State *)malloc(sizeof(State));
    copy->turn = orig->turn;
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            copy->board[i][j] = orig->board[i][j];
        }
    }
    return copy;
}

State *move_piece(State *orig, int i0, int j0, int i1, int j1) {
    State *copy = state_copy(orig);
    copy->turn++;
    copy->board[i1][j1] = copy->board[i0][j0];
    copy->board[i0][j0] = 0;
    return copy;
}

// Returns 1 if winning state for white (meaning black queen has been captured).
// Returns -1 if winning state for black (meaning white queen has been captured).
// Returns 0 for any other state.
int state_utility(State *s) {
    int whiteQueen = 0, blackQueen = 0;
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            if (s->board[i][j] == WHITE_QUEEN) {
                whiteQueen = 1;
                if (blackQueen) return 0;
            } else if (s->board[i][j] == BLACK_QUEEN) {
                blackQueen = 1;
                if (whiteQueen) return 0;
            }
        }
    }
    if (whiteQueen && !blackQueen) return 1;
    if (!whiteQueen && blackQueen) return -1;
    return 0;
}

void state_print(State *s) {
    if (s->turn % 2 == 0) printf("---white's turn (%d)---\n", s->turn);
    else printf("---black's turn (%d)---\n", s->turn);
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            unsigned char piece = s->board[i][j];
            if (!piece) printf(". ");
            else if (piece == WHITE_QUEEN) printf("Q ");
            else if (piece == WHITE_ROOK) printf("R ");
            else if (piece == WHITE_BISHOP) printf("B ");
            else if (piece == WHITE_KNIGHT) printf("N ");
            else if (piece == BLACK_QUEEN) printf("q ");
            else if (piece == BLACK_ROOK) printf("r ");
            else if (piece == BLACK_BISHOP) printf("b ");
            else if (piece == BLACK_KNIGHT) printf("n ");
            else printf("? ");
        }
        printf("\n");
    }
}

List *get_successors(State *s) {
    int color = (s->turn % 2 == 0) ? COLOR_WHITE : COLOR_BLACK;
    List *list = list_create(37);
    
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            unsigned char piece = s->board[i][j];
            if ((piece & COLOR_MASK) != color) continue;
            if ((piece & PIECE_MASK) == QUEEN) {
                for (int ii = i-1; ii >= 0; ii--) {
                    if ((s->board[ii][j] & COLOR_MASK) == color) break;
                    unsigned char prev = s->board[ii][j];
                    State *new = move_piece(s, i, j, ii, j);
                    list_append(list, new);
                    if (prev) break;
                }
                for (int ii = i+1; ii < 4; ii++) {
                    if ((s->board[ii][j] & COLOR_MASK) == color) break;
                    unsigned char prev = s->board[ii][j];
                    State *new = move_piece(s, i, j, ii, j);
                    list_append(list, new);                    
                    if (prev) break;                    
                }
                for (int jj = j-1; jj >= 0; jj--) {
                    if ((s->board[i][jj] & COLOR_MASK) == color) break;
                    unsigned char prev = s->board[i][jj];
                    State *new = move_piece(s, i, j, i, jj);
                    list_append(list, new);
                    if (prev) break;
                }
                for (int jj = j+1; jj < 4; jj++) {
                    if ((s->board[i][jj] & COLOR_MASK) == color) break;
                    unsigned char prev = s->board[i][jj];
                    State *new = move_piece(s, i, j, i, jj);
                    list_append(list, new);
                    if (prev) break;
                }
                for (int ii = i-1, jj = j-1; ii >= 0 && jj >= 0; ii--, jj--) {
                    if ((s->board[ii][jj] & COLOR_MASK) == color) break;
                    unsigned char prev = s->board[ii][jj];
                    State *new = move_piece(s, i, j, ii, jj);
                    list_append(list, new);
                    if (prev) break;
                }
                for (int ii = i+1, jj = j-1; ii < 4 && jj >= 0; ii++, jj--) {
                    if ((s->board[ii][jj] & COLOR_MASK) == color) break;
                    unsigned char prev = s->board[ii][jj];
                    State *new = move_piece(s, i, j, ii, jj);
                    list_append(list, new);
                    if (prev) break;
                }
                for (int ii = i+1, jj = j+1; ii < 4 && jj < 4; ii++, jj++) {
                    if ((s->board[ii][jj] & COLOR_MASK) == color) break;
                    unsigned char prev = s->board[ii][jj];
                    State *new = move_piece(s, i, j, ii, jj);
                    list_append(list, new);
                    if (prev) break;
                }
                for (int ii = i-1, jj = j+1; ii >= 0 && jj < 4; ii--, jj++) {
                    if ((s->board[ii][jj] & COLOR_MASK) == color) break;
                    unsigned char prev = s->board[ii][jj];
                    State *new = move_piece(s, i, j, ii, jj);
                    list_append(list, new);
                    if (prev) break;
                }                
            } else if ((piece & PIECE_MASK) == ROOK) {
                for (int ii = i-1; ii >= 0; ii--) {
                    if ((s->board[ii][j] & COLOR_MASK) == color) break;
                    unsigned char prev = s->board[ii][j];
                    State *new = move_piece(s, i, j, ii, j);
                    list_append(list, new);
                    if (prev) break;
                }
                for (int ii = i+1; ii < 4; ii++) {
                    if ((s->board[ii][j] & COLOR_MASK) == color) break;
                    unsigned char prev = s->board[ii][j];
                    State *new = move_piece(s, i, j, ii, j);
                    list_append(list, new);                    
                    if (prev) break;                    
                }
                for (int jj = j-1; jj >= 0; jj--) {
                    if ((s->board[i][jj] & COLOR_MASK) == color) break;
                    unsigned char prev = s->board[i][jj];
                    State *new = move_piece(s, i, j, i, jj);
                    list_append(list, new);
                    if (prev) break;
                }
                for (int jj = j+1; jj < 4; jj++) {
                    if ((s->board[i][jj] & COLOR_MASK) == color) break;
                    unsigned char prev = s->board[i][jj];
                    State *new = move_piece(s, i, j, i, jj);
                    list_append(list, new);
                    if (prev) break;
                }
            } else if ((piece & PIECE_MASK) == BISHOP) {
                for (int ii = i-1, jj = j-1; ii >= 0 && jj >= 0; ii--, jj--) {
                    if ((s->board[ii][jj] & COLOR_MASK) == color) break;
                    unsigned char prev = s->board[ii][jj];
                    State *new = move_piece(s, i, j, ii, jj);
                    list_append(list, new);
                    if (prev) break;
                }
                for (int ii = i+1, jj = j-1; ii < 4 && jj >= 0; ii++, jj--) {
                    if ((s->board[ii][jj] & COLOR_MASK) == color) break;
                    unsigned char prev = s->board[ii][jj];
                    State *new = move_piece(s, i, j, ii, jj);
                    list_append(list, new);
                    if (prev) break;
                }
                for (int ii = i+1, jj = j+1; ii < 4 && jj < 4; ii++, jj++) {
                    if ((s->board[ii][jj] & COLOR_MASK) == color) break;
                    unsigned char prev = s->board[ii][jj];
                    State *new = move_piece(s, i, j, ii, jj);
                    list_append(list, new);
                    if (prev) break;
                }
                for (int ii = i-1, jj = j+1; ii >= 0 && jj < 4; ii--, jj++) {
                    if ((s->board[ii][jj] & COLOR_MASK) == color) break;
                    unsigned char prev = s->board[ii][jj];
                    State *new = move_piece(s, i, j, ii, jj);
                    list_append(list, new);
                    if (prev) break;
                }
            } else if ((piece & PIECE_MASK) == KNIGHT) {
                int moves[8][2] = {{-2,-1}, {-2,1}, {2,-1}, {2,1}, {-1,-2}, {-1,2}, {1,-2}, {1,2}};
                for (int k = 0; k < 8; k++) {
                    int ii = i + moves[k][0], jj = j + moves[k][1];
                    if (ii < 0 || ii >= 4 || jj < 0 || jj >= 4) continue; // stay within board
                    if ((s->board[ii][jj] & COLOR_MASK) == color) continue; // can't capture own pieces
                    State *new = move_piece(s, i, j, ii, jj);
                    list_append(list, new);
                }
            }
        }
    }

    return list;
}

int minimax_value(State *s, int maxPly) {
    int u = state_utility(s);
    if (u != 0 || s->turn >= maxPly) return u;
    if (s->turn % 2 == 0) { // white's turn to move
        int maxValue = -100;
        List *list = get_successors(s);
        for (int i = 0; i < list->count; i++) {
            int v = minimax_value(list->data[i], maxPly);
            if (v > maxValue) {
                maxValue = v;
                if (maxValue == 1) break; // can't do any better.
            }
        }
        list_destroy(list);
        return maxValue;
    } else { // black's turn to move
        int minValue = 100;
        List *list = get_successors(s);
        for (int i = 0; i < list->count; i++) {
            int v = minimax_value(list->data[i], maxPly);
            if (v < minValue) {
                minValue = v;
                if (minValue == -1) break; // can't do any better
            }
        }
        list_destroy(list);
        return minValue;
    }
}

int main(void) {
    int g, w, b, m;
    scanf("%d", &g);
    while (g--) {
        scanf("%d %d %d", &w, &b, &m);
        State *s = state_new();
        for (int i = 0; i < w; i++) {
            char t, c, r;
            scanf(" %c %c %c", &t, &c, &r);
            int i = r-'1', j = c-'A';
            if (t == 'Q') s->board[i][j] = WHITE_QUEEN;
            else if (t == 'R') s->board[i][j] = WHITE_ROOK;
            else if (t == 'B') s->board[i][j] = WHITE_BISHOP;
            else if (t == 'N') s->board[i][j] = WHITE_KNIGHT;
            else assert(0);
        }
        for (int i = 0; i < b; i++) {
            char t, c, r;
            scanf(" %c %c %c", &t, &c, &r);
            int i = r-'1', j = c-'A';
            if (t == 'Q') s->board[i][j] = BLACK_QUEEN;
            else if (t == 'R') s->board[i][j] = BLACK_ROOK;
            else if (t == 'B') s->board[i][j] = BLACK_BISHOP;
            else if (t == 'N') s->board[i][j] = BLACK_KNIGHT;
            else assert(0);
        }
        if (m % 2 == 0) m--;
        if (minimax_value(s, m) == 1) printf("YES\n");
        else printf("NO\n");
        free(s);
    }

    return 0;
}
                        


                        Solution in C++ :

In  C ++  :









#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cassert>
#include <ctime>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <deque>
#include <list>
#include <stack>
#include <bitset>
#include <algorithm>
#include <iomanip>

using namespace std;

#define forn(i,n) for (int i = 0; i < int(n); i++)
#define ford(i,n) for (int i = int(n) - 1; i >= 0; i--)
#define fore(i,l,r) for (int i = int(l); i < int(r); i++)
#define all(a) a.begin(), a.end()
#define sz(a) int(a.size())
#define mp make_pair
#define pb push_back
#define ft first
#define sc second
#define x first
#define y second

template<typename X> inline X abs(const X& a) { return a < 0 ? -a : a; }
template<typename X> inline X sqr(const X& a) { return a * a; }

typedef long long li;
typedef long double ld;
typedef pair<int, int> pt;

const int INF = int(1e9);
const li INF64 = li(1e18);
const ld EPS = 1e-9;
const ld PI = acosl(ld(-1));

const int N = 4;
int a[N][N];
int w, b, m;

inline int getId (const char& c)
{
	if (c == 'Q')
		return 1;
	if (c == 'N')
		return 2;
	if (c == 'B')
		return 3;
	if (c == 'R')
		return 4;
		
	throw;
}

inline bool read()
{
	if (scanf ("%d%d%d", &w, &b, &m) != 3)
		return false;
		
	memset(a, 0, sizeof a);
		
	forn (i, w)
	{
		char c;
		char x;
		int y;
		assert(scanf (" %c %c%d", &c, &x, &y) == 3);
		
		a[x - 'A'][y - 1] = getId(c);
	}
	
	forn (i, b)
	{
		char c;
		char x;
		int y;
		assert(scanf (" %c %c%d", &c, &x, &y) == 3);

		a[x - 'A'][y - 1] = -getId(c);
	}	
	
	return true;
}

map<li, char> d[20];

const int P = 1009;

const int dx[8] = {0, 1, 0, -1, 1, 1, -1, -1};
const int dy[8] = {1, 0, -1, 0, 1, -1, 1, -1};

const int dx2[8] = {1, 2, 1, 2, -1, -2, -1, -2};
const int dy2[8] = {2, 1, -2, -1, 2, 1, -2, -1};

inline bool valid (int x, int y)
{
	return x >= 0 && y >= 0 && x < 4 && y < 4;
}

int calc (int h, int m)
{
	if (m == 0)
		return 0;
		
	li hash = h;
	forn (i, 4)
		forn (j, 4)
			hash = hash * P + a[i][j];
			
	if (d[m].count(hash))
		return d[m][hash];
		
	if (h == 0)
	{
		forn (x, 4)
			forn (y, 4)
			{
				if (a[x][y] <= 0)
					continue;
					
				if (a[x][y] == 1)
				{
					forn (k, 8)
					{
						int nx = x + dx[k], ny = y + dy[k];
						while (valid(nx, ny) && a[nx][ny] <= 0)
						{
							int old = a[nx][ny];
							a[nx][ny] = a[x][y];
							a[x][y] = 0;
							
							if (old == -1 || calc(h ^ 1, m - 1))
							{
								a[x][y] = a[nx][ny];
								a[nx][ny] = old;					

								return d[m][hash] = 1;
							}
								
							a[x][y] = a[nx][ny];
							a[nx][ny] = old;
							
							if (a[nx][ny] != 0)
								break;
							
							nx += dx[k], ny += dy[k];
						}
					}
				}
				
				if (a[x][y] == 2)
				{
					forn (k, 8)
					{
						int nx = x + dx2[k], ny = y + dy2[k];
						
						if (!valid(nx, ny) || a[nx][ny] > 0)
							continue;

    					int old = a[nx][ny];
    					a[nx][ny] = a[x][y];
    					a[x][y] = 0;
    					
    					if (old == -1 || calc(h ^ 1, m - 1))
    					{
	    					a[x][y] = a[nx][ny];
    						a[nx][ny] = old;
    					
    						return d[m][hash] = 1;
    					}
    						
    					a[x][y] = a[nx][ny];
    					a[nx][ny] = old;
					}					
				}
				
				if (a[x][y] == 3)
				{
					fore (k, 4, 8)
					{
						int nx = x + dx[k], ny = y + dy[k];
						while (valid(nx, ny) && a[nx][ny] <= 0)
						{
							int old = a[nx][ny];
							a[nx][ny] = a[x][y];
							a[x][y] = 0;
							
							if (old == -1 || calc(h ^ 1, m - 1))
							{
								a[x][y] = a[nx][ny];
								a[nx][ny] = old;
							
								return d[m][hash] = 1;
							}
							
							a[x][y] = a[nx][ny];
							a[nx][ny] = old;							
								
							if (a[nx][ny] != 0)
								break;
							
							nx += dx[k], ny += dy[k];
						}
					}
				}

				if (a[x][y] == 4)
				{
					forn (k, 4)
					{
						int nx = x + dx[k], ny = y + dy[k];
						while (valid(nx, ny) && a[nx][ny] <= 0)
						{
							int old = a[nx][ny];
							a[nx][ny] = a[x][y];
							a[x][y] = 0;
							
							if (old == -1 || calc(h ^ 1, m - 1))
							{
								a[x][y] = a[nx][ny];
								a[nx][ny] = old;
														
								return d[m][hash] = 1;
							}
							
							a[x][y] = a[nx][ny];
							a[nx][ny] = old;							
															
							if (a[nx][ny] != 0)
								break;
							
							nx += dx[k], ny += dy[k];
						}
					}
				}				
			}
			
		return d[m][hash] = 0;
	}
	else
	{
		forn (x, 4)
			forn (y, 4)
			{
				if (a[x][y] >= 0)
					continue;
					
				if (a[x][y] == -1)
				{
					forn (k, 8)
					{
						int nx = x + dx[k], ny = y + dy[k];
						while (valid(nx, ny) && a[nx][ny] >= 0)
						{
							int old = a[nx][ny];
							a[nx][ny] = a[x][y];
							a[x][y] = 0;
							
							if (old == 1 || !calc(h ^ 1, m - 1))
							{
								a[x][y] = a[nx][ny];
								a[nx][ny] = old;
														
								return d[m][hash] = 0;
							}
								
							a[x][y] = a[nx][ny];
							a[nx][ny] = old;
							
							if (a[nx][ny] != 0)
								break;
							
							nx += dx[k], ny += dy[k];
						}
					}
				}
				
				if (a[x][y] == -2)
				{
					forn (k, 8)
					{
						int nx = x + dx2[k], ny = y + dy2[k];
						
						if (!valid(nx, ny) || a[nx][ny] < 0)
							continue;						

    					int old = a[nx][ny];
    					a[nx][ny] = a[x][y];
    					a[x][y] = 0;
    					
    					if (old == 1 || !calc(h ^ 1, m - 1))
    					{
	    					a[x][y] = a[nx][ny];
    						a[nx][ny] = old;
    					
    						return d[m][hash] = 0;
    					}
    						
    					a[x][y] = a[nx][ny];
    					a[nx][ny] = old;
					}					
				}
				
				if (a[x][y] == -3)
				{
					fore (k, 4, 8)
					{
						int nx = x + dx[k], ny = y + dy[k];
						while (valid(nx, ny) && a[nx][ny] >= 0)
						{
							int old = a[nx][ny];
							a[nx][ny] = a[x][y];
							a[x][y] = 0;
							
							if (old == 1 || !calc(h ^ 1, m - 1))
							{
								a[x][y] = a[nx][ny];
								a[nx][ny] = old;
												
								return d[m][hash] = 0;
							}
								
							a[x][y] = a[nx][ny];
							a[nx][ny] = old;
							
							if (a[nx][ny] != 0)
								break;
							
							nx += dx[k], ny += dy[k];
						}
					}
				}

				if (a[x][y] == -4)
				{
					forn (k, 4)
					{
						int nx = x + dx[k], ny = y + dy[k];
						while (valid(nx, ny) && a[nx][ny] >= 0)
						{
							int old = a[nx][ny];
							a[nx][ny] = a[x][y];
							a[x][y] = 0;
							
							if (old == 1 || !calc(h ^ 1, m - 1))
							{
								a[x][y] = a[nx][ny];
								a[nx][ny] = old;
							
								return d[m][hash] = 0;
							}
								
							a[x][y] = a[nx][ny];
							a[nx][ny] = old;
							
							if (a[nx][ny] != 0)
								break;
							
							nx += dx[k], ny += dy[k];
						}
					}
				}				
			}	
			
		return d[m][hash] = 1;
	}
}

inline void solve()
{
	forn (i, m + 1)
		d[i].clear();
		
	int ans = calc(0, m);
	//cerr << ans << endl;
	if (ans)
		puts("YES");
	else
		puts("NO");
}

int main()
{
#ifdef SU2_PROJ
	assert(freopen("input.txt", "r", stdin));
	assert(freopen("output.txt", "w", stdout));
#endif

	cout << setprecision(25) << fixed;
	cerr << setprecision(10) << fixed;

	srand(int(time(NULL)));
	
	int testCnt;
	assert(scanf ("%d", &testCnt) == 1);
	
	forn (test, testCnt)
	{
		assert(read());
		solve();
	}

#ifdef SU2_PROJ
	cerr << "TIME: " << clock() << endl;
#endif

	return 0;
}
                    


                        Solution in Java :

In  Java :








import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;

public class Solution {

    public static int[] queen = { 1, 0, -1, 0, 0, 1, 0, -1, 2, 0, -2, 0, 0, 2, 0, -2, 3, 0, -3, 0, 0, 3, 0, -3, 1, 1,
			-1, -1, 1, -1, -1, 1, 2, 2, -2, -2, 2, -2, -2, 2, 3, 3, -3, -3, 3, -3, -3, 3 };
	public static int[] rook = { 1, 0, -1, 0, 0, 1, 0, -1, 2, 0, -2, 0, 0, 2, 0, -2, 3, 0, -3, 0, 0, 3, 0, -3 };
	public static int[] bishop = { 1, 1, -1, -1, 1, -1, -1, 1, 2, 2, -2, -2, 2, -2, -2, 2, 3, 3, -3, -3, 3, -3, -3, 3 };
	public static int[] knight = { 1, 2, -1, -2, 2, 1, -2, -1, 1, -2, -1, 2, 2, -1, -2, 1 };

	public abstract static class Piece
	{
		final boolean white;
		final int[] moves;
		final boolean canJump;
		int x, y;
		boolean taken;

		public Piece(int x, int y, boolean white, int[] moves, boolean canJump)
		{
			this.white = white;
			this.x = x;
			this.y = y;
			this.moves = moves;
			this.canJump = canJump;
		}

		int count()
		{
			return moves.length / 2;
		}

		boolean canMove(int number, Piece[][] board)
		{
			int dx = moves[2 * number];
			int dy = moves[2 * number + 1];
			int x = this.x + dx;
			int y = this.y + dy;
			if (!(0 <= x && x <= 3 && 0 <= y && y <= 3))
			{
				return false;
			}
			Piece taking = board[x][y];
			if (taking != null && taking.white == white)
			{
				return false;
			}
			if (canJump)
			{
				return true;
			}
			int steps = Math.max(Math.abs(dx), Math.abs(dy)) - 1;
			int sx = dx == 0 ? 0 : dx > 0 ? 1 : -1;
			int sy = dy == 0 ? 0 : dy > 0 ? 1 : -1;
			for (int i = 1; i <= steps; i++)
			{
				if (board[this.x + sx * i][this.y + sy * i] != null)
				{
					return false;
				}
			}
			return true;
		}

		void move(int number, boolean reverse)
		{
			number += !reverse ? 0 : number % 2 == 0 ? 1 : -1;
			this.x += moves[2 * number];
			this.y += moves[2 * number + 1];
		}

		@Override
		public String toString()
		{
			return (white ? "white " : "black ") + getClass().getSimpleName();
		}
	}

	public static class Queen extends Piece
	{
		public Queen(int x, int y, boolean white)
		{
			super(x, y, white, queen, false);
		}
	}

	public static class Rook extends Piece
	{
		public Rook(int x, int y, boolean white)
		{
			super(x, y, white, rook, false);
		}
	}

	public static class Bishop extends Piece
	{
		public Bishop(int x, int y, boolean white)
		{
			super(x, y, white, bishop, false);
		}
	}

	public static class Knight extends Piece
	{
		public Knight(int x, int y, boolean white)
		{
			super(x, y, white, knight, true);
		}
	}

	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		int games = sc.nextInt();
		while (games-- > 0)
		{
			int w = sc.nextInt();
			int b = sc.nextInt();
			int m = sc.nextInt();
			Piece board[][] = new Piece[4][4];
			List<Piece> white = new ArrayList<>();
			List<Piece> black = new ArrayList<>();
			for (int j = 0; j < 2; j++)
			{
				for (int i = 0; i < (j == 0 ? w : b); i++)
				{
					char p = sc.next()
							.charAt(0);
					int x = sc.next()
							.charAt(0) - 'A';
					int y = sc.nextInt() - 1;
					Piece piece = p == 'Q' ? new Queen(x, y, j == 0)
							: p == 'R' ? new Rook(x, y, j == 0)
									: p == 'B' ? new Bishop(x, y, j == 0) : new Knight(x, y, j == 0);
					board[x][y] = piece;
					(j == 0 ? white : black).add(piece);
				}
			}

			boolean win = move(true, white, black, board, m);
			System.out.println(win ? "YES" : "NO");
		}
	}

	public static boolean move(boolean whiteTurn, List<Piece> white, List<Piece> black, Piece[][] board, int m)
	{
		if (m <= 0)
		{
			return false;
		}
		boolean all = !whiteTurn;
		List<Piece> pieces = whiteTurn ? white : black;
		for (Piece piece : pieces)
		{
			if (piece.taken)
			{
				continue;
			}
			for (int i = 0; i < piece.count(); i++)
			{
				if (piece.canMove(i, board))
				{
					board[piece.x][piece.y] = null;
					piece.move(i, false);
					Piece taken = board[piece.x][piece.y];
					board[piece.x][piece.y] = piece;

					if (taken != null)
					{
						taken.taken = true;
					}

					try
					{
						if (taken instanceof Queen)
						{
							return whiteTurn;
						}

						boolean result = move(!whiteTurn, white, black, board, m - 1);

						if (result && whiteTurn)
						{
							return true;
						}
						all &= result;
					}
					finally
					{
						if (taken != null)
						{
							taken.taken = false;
						}

						board[piece.x][piece.y] = taken;
						piece.move(i, true);
						board[piece.x][piece.y] = piece;
					}
				}
			}
		}
		return all;
	}
}
                    


                        Solution in Python : 
                            
In  Python3 :








N = 4
D = ((1, 0), (0, 1), (-1, 0), (0, -1), (1, 1), (-1, 1), (-1, -1), (1, -1), (2, 1), (1, 2), (-1, 2), (-2, 1), (-2, -1), (-1, -2), (1, -2), (2, -1))
FIGURES = "QNBR"
RANGE = ((0, 8), (8, 16), (4, 8), (0, 4))


def solve():
	w, b, m = map(int, input().split())
	m -= (m + 1) % 2
	field = [[0] * N for _ in range(N)]
	for i in range(w + b):
		figure, col, row = input().split()
		col = ord(col) - ord('A')
		row = int(row) - 1
		figure = FIGURES.find(figure) + 1
		if i >= w:
			figure *= -1
		field[row][col] = figure
	return search(tuple(map(tuple, field)), m)

def search(field, m):
	if (field, m) in memo:
		return memo[(field, m)]
	white = (m % 2 == 1)
	for i in range(N):
		for j in range(N):
			f = field[i][j]
			if f == 0 or ((f > 0) != white):
				continue
			for d in range(*RANGE[abs(f) - 1]):
				dx, dy = D[d]
				x, y = i, j
				while True:
					x += dx
					y += dy
					if x < 0 or x >= N or y < 0 or y >= N:
						break
					g = field[x][y]
					if g != 0 and (g > 0) == (f > 0):
						break
					if abs(g) == 1:
						memo[(field, m)] = white
						return white
					if m > 1:
						new = list(map(list, field))
						new[i][j] = 0
						new[x][y] = f
						new = tuple(map(tuple, new))
						s = search(new, m - 1)
						if white == s:
							memo[(field, m)] = s
							return s
					if g:
						break
	memo[(field, m)] = not white
	return not white


memo = {}
for _ in range(int(input())):
	print("YES" if solve() else "NO")
                    


View More Similar Problems

2D Array-DS

Given a 6*6 2D Array, arr: 1 1 1 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 An hourglass in A is a subset of values with indices falling in this pattern in arr's graphical representation: a b c d e f g There are 16 hourglasses in arr. An hourglass sum is the sum of an hourglass' values. Calculate the hourglass sum for every hourglass in arr, then print t

View Solution →

Dynamic Array

Create a list, seqList, of n empty sequences, where each sequence is indexed from 0 to n-1. The elements within each of the n sequences also use 0-indexing. Create an integer, lastAnswer, and initialize it to 0. There are 2 types of queries that can be performed on the list of sequences: 1. Query: 1 x y a. Find the sequence, seq, at index ((x xor lastAnswer)%n) in seqList.

View Solution →

Left Rotation

A left rotation operation on an array of size n shifts each of the array's elements 1 unit to the left. Given an integer, d, rotate the array that many steps left and return the result. Example: d=2 arr=[1,2,3,4,5] After 2 rotations, arr'=[3,4,5,1,2]. Function Description: Complete the rotateLeft function in the editor below. rotateLeft has the following parameters: 1. int d

View Solution →

Sparse Arrays

There is a collection of input strings and a collection of query strings. For each query string, determine how many times it occurs in the list of input strings. Return an array of the results. Example: strings=['ab', 'ab', 'abc'] queries=['ab', 'abc', 'bc'] There are instances of 'ab', 1 of 'abc' and 0 of 'bc'. For each query, add an element to the return array, results=[2,1,0]. Fun

View Solution →

Array Manipulation

Starting with a 1-indexed array of zeros and a list of operations, for each operation add a value to each of the array element between two given indices, inclusive. Once all operations have been performed, return the maximum value in the array. Example: n=10 queries=[[1,5,3], [4,8,7], [6,9,1]] Queries are interpreted as follows: a b k 1 5 3 4 8 7 6 9 1 Add the valu

View Solution →

Print the Elements of a Linked List

This is an to practice traversing a linked list. Given a pointer to the head node of a linked list, print each node's data element, one per line. If the head pointer is null (indicating the list is empty), there is nothing to print. Function Description: Complete the printLinkedList function in the editor below. printLinkedList has the following parameter(s): 1.SinglyLinkedListNode

View Solution →