Google中国2015校园招聘笔试Round D APAC Test Problem D. Itz Chess

Problem

Given an arranged chess board with pieces, figure out the total number of different ways in which any piece can be killed in one move. Note: in this problem, the pieces can be killed despite of the color.

For example, if there are 3 pieces King is at B2, Pawn at A1 and Queen at H8 then the total number of pieces that an be killed is 3. H8-Q can kill B2-K, A1-P can kill B2-K, B2-K can kill A1-P

A position on the chess board is represented as A1, A2... A8,B1.. H8

Pieces are represented as

  • (K) King can move in 8 direction by one place.
  • (Q) Queen can move in 8 direction by any number of places, but can't overtake another piece.
  • (R) Rook can only move vertically or horitonzally, but can't overtake another piece.
  • (B) Bishop can only move diagonally, but can't overtake another piece.
  • (N) Knights can move to a square that is two squares horizontally and one square vertically OR one squares horizontally and two square vertically.
  • (P) Pawn can only kill by moving diagonally upwards (towards higher number i.e. A -> B, B->C and so on).

Input

The first line of the input gives the number of test cases, TT Test cases follow. Each test case consists of the number of pieces , NN lines follow, each line mentions where a piece is present followed by - with the piece type

Output

For each test case, output one line containing "Case #x: y", where x is the test case number (starting from 1) and y is the the total number of different ways in which any piece can be killed.

Limits

1 ≤ T ≤ 100.

Small dataset

1 ≤ N ≤ 10.
Pieces can include K, P

Large dataset

1 ≤ N ≤ 64.

Sample


Input 
 

Output 
 
2
2
A1-K
A8-Q

3
B2-K
A1-P
H8-Q

Case #1: 1
Case #2: 3

类型:其他  难度:2

题意:给出一个国际象棋棋盘(给出的图错了,应将棋子固定,坐标顺时针旋转90度),以及给出若干棋子的类型为位置(不分黑白)。求有多少种一步吃子的方法,即遍历每个棋子,将每个棋子一步能吃子的情况累加。

棋子种类与吃子规则:

  • (K) 国王,每次移动一格,8个方向均可
  • (Q) 王后,每次移动多格,8个方向均可
  • (R) 车,每次移动多格,只能向水平和垂直的4个方向移动
  • (B) 象,每次移动多格,只能向对角线的4个方向移动
  • (N) 马,按“日“字移动,每步有8种走法
  • (P) 兵,吃子的时候,只能向斜前方走一步吃子,每步只有2种走法,即若子在D2,只能吃E1和E3
  • 所有棋子均不能越过棋子吃子

分析:遍历每个棋子,看每个棋子走一步的所有情况中有多少能吃子,累加即可。关键在于走法比较繁琐。如何能快速的抽象化每种棋子的吃子模式,我的方法是,用mp[i][j]记录棋盘上(i,j)的棋子种类。用dir[][2]记录某个棋子的下一步的所有情况的坐标变化。那么可得K的dir数组为,int dirK[8][2] = {{-1,-1},{-1,0},{-1,1},{1,-1},{1,0},{1,1},{0,-1},{0,1}};,其他棋子以此类推。

对于每个棋子,判断棋子种类,对于只能移动一格的棋子,用一层循环遍历其下一步的位置,若该位置有棋子,答案计数ans++;

对于能移动多格的棋子,加一个内层循环记录在某个方向上的步数,注意若在这个方向遇到棋子,ans++,并跳出内层循环,以满足所有棋子均不能越过棋子吃子的条件。

代码如下:

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <string>
#include <set>
#include <map>
using namespace std;

int n;
char mp[10][10];
int dirK[8][2] = {{-1,-1},{-1,0},{-1,1},{1,-1},{1,0},{1,1},{0,-1},{0,1}};
int dirR[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
int dirB[4][2] = {{-1,-1},{-1,1},{1,-1},{1,1}};
int dirN[8][2] = {{-1,-2},{-1,2},{1,-2},{1,2},{-2,-1},{-2,1},{2,-1},{2,1}};
int dirP[2][2] = {{1,-1},{1,1}};

int fun(int i,int j)
{
    int ans = 0;
    if(mp[i][j]=='K')
    {
        for(int k=0; k<8; ++k)
        {
            int ni = i+dirK[k][0];
            int nj = j+dirK[k][1];
            if(ni>=0 && ni<8 && nj>=0 && nj<8 && mp[ni][nj]!=0)
                ++ans;
        }
    }
    else if(mp[i][j]=='Q')
    {
        for(int k=0; k<8; ++k)
        {
            for(int l=1; l<8; ++l)
            {
                int ni = i+dirK[k][0]*l;
                int nj = j+dirK[k][1]*l;
                if(ni>=0 && ni<8 && nj>=0 && nj<8 && mp[ni][nj]!=0)
                {
                    ++ans;
                    break;
                }
            }
        }
    }
    else if(mp[i][j]=='R')
    {
        for(int k=0; k<4; ++k)
        {
            for(int l=1; l<8; ++l)
            {
                int ni = i+dirR[k][0]*l;
                int nj = j+dirR[k][1]*l;
                if(ni>=0 && ni<8 && nj>=0 && nj<8 && mp[ni][nj]!=0)
                {
                    ++ans;
                    break;
                }
            }
        }
    }
    else if(mp[i][j]=='B')
    {
        for(int k=0; k<4; ++k)
        {
            for(int l=1; l<8; ++l)
            {
                int ni = i+dirB[k][0]*l;
                int nj = j+dirB[k][1]*l;
                if(ni>=0 && ni<8 && nj>=0 && nj<8 && mp[ni][nj]!=0)
                {
                    ++ans;
                    break;
                }
            }
        }
    }
    else if(mp[i][j]=='N')
    {
        for(int k=0; k<8; ++k)
        {
            int ni = i+dirN[k][0];
            int nj = j+dirN[k][1];
            if(ni>=0 && ni<8 && nj>=0 && nj<8 && mp[ni][nj]!=0)
                ++ans;
        }
    }
    else
    {
        for(int k=0; k<2; ++k)
        {
            int ni = i+dirP[k][0];
            int nj = j+dirP[k][1];
            if(ni>=0 && ni<8 && nj>=0 && nj<8 && mp[ni][nj]!=0)
                ++ans;
        }
    }
    return ans;
}

int main() {
    freopen("D-small-practice.in", "r", stdin);
    freopen("D-small-practice.out", "w", stdout);

    int t;
    scanf("%d",&t);

    for(int cnt=1; cnt<=t; ++cnt)
    {
        scanf("%d",&n);
        char tmp[20];
        memset(mp,0,sizeof(mp));
        
        for(int i=0; i<n; ++i)
        {
            scanf("%s",tmp);
            mp[tmp[0]-'A'][tmp[1]-'1'] = tmp[3];
        }
        int ans = 0;
        for(int i=0; i<8; ++i)
            for(int j=0; j<8; ++j)
            {
                if(mp[i][j]!=0)
                {
                    ans += fun(i,j);
                }
            }
        printf("Case #%d: %d\n",cnt,ans);
    }
}


你可能感兴趣的:(C++,Google,笔试)