题目意思:
类似于八皇后问题,但不是放置皇后,是计算安全位置。有三种棋子,皇后、骑士和卒(pawn,貌似不是这个意思)。皇后是全方向攻击(八个方向),距离不限,但是会被阻挡;骑士只能走“日”字形,也有八个方向,不受阻挡;卒子不能动。然后计算整个棋盘的安全位置(皇后和骑士都无法攻击到的位置)。
解题思路:
最简单的,逐个遍历皇后和骑士(卒子不能攻击当然先忽略),然后记录该棋子的能攻击的位置,到最后统计没有记录的格子就是安全格子数。
曾经想过用计算几何的方法,把皇后的轨迹当直线,后来又懒得写,不过感觉不行。
代码:
#include <iostream>
#include <cstring>
using namespace std;
int qs;
int que[ 101 ][ 2 ];
int ks;
int kni[ 101 ][ 2 ];
int ps;
int paw[ 101 ][ 2 ];
char state[ 1001 ][ 1001 ];
int qd[ 8 ][ 2 ] = { -1, 0, -1, 1, 0, 1, 1, 1, 1, 0, 1, -1, 0, -1, -1, -1 };
// 计算所有皇后能吃到的格子
int calq( int row, int col )
{
int i, j, r, c;
int num = 0;
for( i = 0; i < qs; i++ )
{
// 循环八个方向
for( j = 0; j < 8; j++ ){
r = que[ i ][ 0 ] + qd[ j ][ 0 ]; // 皇后呀
c = que[ i ][ 1 ] + qd[ j ][ 1 ];
while( ( r > 0 && r <= row ) && ( c > 0 && c <= col ) )
{
// 有阻挡
if( state[ r ][ c ] > 1 )
break;
// 标记访问
if( state[ r ][ c ] < 1 ){
state[ r ][ c ] = 1;
num++;
}
r += qd[ j ][ 0 ];
c += qd[ j ][ 1 ];
}
}
}
return num;
}
int kd[ 8 ][ 2 ] = { -2, 1, -1, 2, 1, 2, 2, 1, 2, -1, 1, -2, -1, -2, -2, -1};
// 计算所有骑士能吃到的格子
int calk( int row, int col )
{
int i, j, r, c;
int num = 0;
for( i = 0; i < ks; i++ )
{
// 遍历八个方向
for( j = 0; j < 8; j++ )
{
r = kni[ i ][ 0 ] + kd[ j ][ 0 ]; // 骑士呀
c = kni[ i ][ 1 ] + kd[ j ][ 1 ];
// 不会阻挡
if( ( r > 0 && r <= row ) && ( c > 0 && c <= col ) ){
if( state[ r ][ c ] < 1 ){
state[ r ][ c ] = 1;
num++;
}
r += kd[ j ][ 0 ];
c += kd[ j ][ 1 ];
}
}
}
return num;
}
int main()
{
int row, col, i;
int r, c;
int times = 0;
while( cin >> row >> col )
{
if( row + col == 0 )
break;
times++;
memset( state, 0, sizeof( state ) );
// 读入皇后
cin >> qs;
for( i = 0; i < qs; i++ )
{
cin >> r >> c;
que[ i ][ 0 ] = r;
que[ i ][ 1 ] = c;
state[ r ][ c ] = 3;
}
// 读入骑士
cin >> ks;
for( i = 0; i < ks; i++ )
{
cin >> r >> c;
kni[ i ][ 0 ] = r;
kni[ i ][ 1 ] = c;
state[ r ][ c ] = 3;
}
// 读入pawn
cin >> ps;
for( i = 0; i < ps; i++ )
{
cin >> r >> c;
paw[ i ][ 0 ] = r;
paw[ i ][ 1 ] = c;
state[ r ][ c ] = 3;
}
int number = row * col - qs - calq( row, col ) - ks - calk( row, col ) - ps;
cout << "Board " << times << " has " << number << " safe squares." << endl;
}
return 0;
}
时间:0.01s 应该还算及格吧。
1、因为题目空间给出的要求有64M,比较多,所以可以稍微浪费点使用,例如说那个数组int kd[ 8 ][ 2 ] = { -2, 1, -1, 2, 1, 2, 2, 1, 2, -1, 1, -2, -1, -2, -2, -1};,这样做有助于节省一点判断时间;
2、个人犯糊涂,把变量名搞错,WA了两三次。。。