sicily1172 Queens, Knights and Pawns

题目链接:http://soj.sysu.edu.cn/1172

题目大意:在一个棋盘上,放着皇后、骑士和兵三种棋子。其中皇后有八个方向可以占位(即在该方向上的位置不能再放棋子),但是如果其遇到任何的另一个棋子,其在该方向上的在两个棋子外的部分将不会被占位,比如:一个4*4的棋盘,有一个骑士在(1,2),有一个皇后在(1,4)那么(1,1)将不会被皇后占位;对于骑士,其占位的方向是“日”字型的,即2*3的矩阵的对角;而兵只是简单的在自己的位置上占位而不提供其他功能。

解题思路:直接按题目要求模拟。

这里需要注意的是皇后受阻挡并不会发生在由其他棋子所产生的占位的情况下。比如下图中,在(1,2)和(3,4)处有一个皇后,那么黑色1 的方格就是(1,2)皇后产生的占位,此时对于(3,4)的皇后,其所产生的占位是红色 1 和蓝色 1 的方格。这里需要注意的就是蓝色 1 这个位置,(3,4)皇后并不会因为有(3,2)的占位而受阻,其仍然会对(3,1)发生作用。


#include <stdio.h>

//  用于记录棋盘上该位置是否还能用,0 表示能用,1和2表示不能用
//  其中,1表示放上棋子后由棋子所产生的占位,2表示棋子本身的占位
int occupied[1010][1010];
struct Point	//  棋子坐标
{
	int x;		//  横坐标
	int y;		//  纵坐标
};

int main()
{
	int n, m, cnt = 1, queen_num, knight_num, pawn_num, count, x, y;
	Point queens[110], knight[110], pawn[110];
	while (1)
	{
		scanf("%d %d", &m, &n);
		if (n == 0 && m == 0)
			break;
		//  初始化棋盘所有位置为未被占用
		for (int i = 0; i < m + 2; i++)
			for (int j = 0; j < n + 2; j++)
				occupied[i][j] = 0;
		//  读皇后的数据并初始化
		scanf("%d", &queen_num);
		for (int i = 0; i < queen_num; i++)
		{
			scanf("%d %d", &queens[i].x, &queens[i].y);
			occupied[queens[i].x][queens[i].y] = 2;
		}
		//  读骑士的数据并初始化
		scanf("%d", &knight_num);
		for (int i = 0; i < knight_num; i++)
		{
			scanf("%d %d", &knight[i].x, &knight[i].y);
			occupied[knight[i].x][knight[i].y] = 2;
		}
		//  读兵的数据并初始化
		scanf("%d", &pawn_num);
		for (int i = 0; i < pawn_num; i++)
		{
			scanf("%d %d", &pawn[i].x, &pawn[i].y);
			occupied[pawn[i].x][pawn[i].y] = 2;
		}
		//  更新皇后棋子所产生的占位
		for (int k = 0; k < queen_num; k++)
		{
			x = queens[k].x;
			y = queens[k].y;
			//  竖直向上方向
			for (int i = x - 1; i > 0; i--)
			{
				if (occupied[i][y] == 2)
					break;
				occupied[i][y] = 1;
			}
			//  竖直向下方向
			for (int i = x + 1; i <= m; i++)
			{
				if (occupied[i][y] == 2)
					break;
				occupied[i][y] = 1;
			}
			//  水平向左方向
			for (int i = y - 1; i > 0; i--)
			{
				if (occupied[x][i] == 2)
					break;
				occupied[x][i] = 1;
			}
			//  水平向右方向
			for (int i = y + 1; i <= n; i++)
			{
				if (occupied[x][i] == 2)
					break;
				occupied[x][i] = 1;
			}
			//  左下方向
			for (int i = x + 1, j = y - 1; i <= m && j > 0; i++, j--)
			{
				if (occupied[i][j] == 2)
					break;
				occupied[i][j] = 1;
			}
			//  左上方向
			for (int i = x - 1, j = y - 1; i >0 && j > 0; i--, j--)
			{
				if (occupied[i][j] == 2)
					break;
				occupied[i][j] = 1;
			}
			//  右上方向
			for (int i = x - 1, j = y + 1; i > 0 && j <= n; i--, j++)
			{
				if (occupied[i][j] == 2)
					break;
				occupied[i][j] = 1;
			}
			//  右下方向
			for (int i = x + 1, j = y + 1; i <= m && j <= n; i++, j++)
			{
				if (occupied[i][j] == 2)
					break;
				occupied[i][j] = 1;
			}
		}
		//  更新骑士棋子所产生的占位
		for (int i = 0; i < knight_num; i++)
		{
			x = knight[i].x;
			y = knight[i].y;
			if (x + 1 <= m && y + 2 <= n)
				occupied[x + 1][y + 2] = 1;
			if (x - 1 > 0 && y + 2 <= n)
				occupied[x - 1][y + 2] = 1;
			if (x + 2 <= m && y + 1 <= n)
				occupied[x + 2][y + 1] = 1;
			if (x - 2 > 0 && y + 1 <= n)
				occupied[x - 2][y + 1] = 1;
			if (x + 1 <= m && y - 2 > 0)
				occupied[x + 1][y - 2] = 1;
			if (x - 1 > 0 && y - 2 > 0)
				occupied[x - 1][y - 2] = 1;
			if (x - 2 > 0 && y - 1 > 0)
				occupied[x - 2][y - 1] = 1;
			if (x + 2 <= m && y - 1 > 0)
				occupied[x + 2][y - 1] = 1;
		}
		//  计算还有多少个位置没被占用
		count = 0;
		for (int i = 1; i <= m; i++)
			for (int j = 1; j <= n; j++)
				if (occupied[i][j] == 0)
					count++;
		printf("Board %d has %d safe squares.\n", cnt++, count);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值