USACO 3.3.3 camelot解题思路及C++代码


几个世纪前,亚瑟王和圆桌骑士过去每年在元旦见面,以庆祝他们的团聚。为了纪念这些事件,我们考虑一个棋手游戏,一个棋子国王和几个骑士棋子放在一个方格内,而没有两个骑士会在同一个方格内。
该示例板是标准的8x8正方形阵列:
在这里插入图片描述
国王可以移动到任何相邻的方格中去,只要它不落到棋盘方格外:
在这里插入图片描述
骑士可以跳跃下图所示方格中,只要落到棋盘方格外:
在这里插入图片描述
在游戏过程中,玩家可以在同一方格中放置多个棋子。假定方格足够大,它永远不会成为任何其他块自由移动的障碍。
玩家的目标是移动棋子,以便以最少步数移动国王和骑士,并将它们集中在一个方格中。为此,他必须按照上述规则移动国王和骑士。另外,每当国王和一个或多个骑士放置在同一方格中时,玩家都可以选择将国王和某个骑士一起移动,一直随骑士最后一个集中方格中。骑士与国王一起移动骑士时,只计算骑士的步数。
编写一个程序来计算玩家为产生聚会而必须执行的最小移动步数。他们可以集中在任何一个方格中。

程序名称camelot
输入格式
第1行: 两个以空格分隔的整数:R,C,板上的行数和列数。最多不超过26列,最多不超过30行。
第2行:一直到最后: 输入文件包含一系列用空格分隔的字母/数字对,每行1个或更多。第一对代表国王所在方格的位置;随后的每对代表骑士的位置。可能有0位骑士,也可能骑士可能会填满这个棋盘。行号从1开始编号;列号是以’A’开头的大写字符。
输入示例(文件camelot.in
8 8
D 4
A 3 A 8
H 1 H 8
国王位于D4。有四个骑士,分别位于A3,A8,H1和H8。
输出格式
一行表示集中到一起所需要的最小移动步数。
输出示范(文件camelot.out)
10
输出示范详细说明
他们集中在B5方格中。
骑士1:A3-B5(1步)
骑士2:A8-C7-B5(2步)
骑士3:H1-G3-F5-D4(接国王)-B5(4步)
骑士4:H8-F7- D6-B5(3步)
1 + 2 + 4 + 3 = 10步

解题算法思路:

国王和骑士可能集中在任何一个方格中。
采用BFS算法,计算骑士们到达棋盘每个方格所需要的步数。计算过程中,同时记录下所有的路径。
对于每个方格,计算所有骑士到达这个方格所需要的步数,得到总步数。
对于国王与骑士汇合步数计算。对于每个方格,BFS计算中记录了每个骑士到达这个方格的路径,在这些路径上找到最接近骑士的方格,得到国王与每个骑士汇合的步数。
注意:国王从(x1,y1)到达(x2,y2)的距离为max(abs(x1-x2),abs(y1-y2))。
为了节约计算时间,棋盘每个方格的边在棋盘初始化的时候,预先生成,在每个骑士进行BFS搜索的时候,可以更加方便使用。
棋盘方格全部使用一位数组计算,提供速度。
同时注意处理一下特殊情况:只有国王的情况下,不需要移动,步数为0。

源代码

/*
ID:  
LANG: C++11
PROG: camelot
*/
#include <fstream>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
#include <iostream>
#include <string>
#include <algorithm>
//#include <bits/stdc++.h> 
using namespace std;
#define FOR(i, a, b) for (int i=a; i<(b); i++)
#define F0R(i, a) for (int i=0; i<(a); i++)
#define FORd(i,a,b) for (int i = (b)-1; i >= a; i--)
#define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--)
#define MAX_R 30
#define MAX_C 26

int R,C;
int king, knight[MAX_R*MAX_C];
int knightNum;

ifstream fin("camelot.in");
ofstream fout("camelot.out");
struct Node {
   
	int x;
	int y;
	int isVisit;
	int knightMoves[8];
};
struct Point {
   
	int x;
	int y;
};

Point knightOffset[8] = {
    {
   -1,-2},{
   -1,2},{
   -2,-1},{
   -2,1},{
   1,-2},{
   1,2},{
   2,-1},{
   2,1} };
class Chess {
   
	int rsize,csize;
	Node *grid;
	public:
		Chess(int rsz, int csz) {
   
			rsize = rsz; csize = csz;
			grid = (Node *)malloc(rsize*csize * sizeof(Node)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值