原题:
在8*8的棋盘上分布着n个骑士,他们想约在某一格中聚会.骑士每天可以像国际象棋中的马那样移动一次.请你计算n个骑士的最早聚会地点和要走多少天.要求尽早聚会,且n个人走的总步数最少,先到的骑士可以不再移动等待其它骑士.
输入:
从键盘输入n(0<n<=64),然后依次输入n个骑士的初始位置xi,yi(0<=xi,yi<=7)
输出
:以空格分隔的三个整数,分别为聚会点的x,y值,以及要走多少天
对问题的分析:为了解决这个问题,显然我们得想办法能计算出骑士从棋盘上的某个格子到其它格子需要的最少步数.
(另一方面,很容易可以证明骑士可以从棋盘上任意一个格子到达另一个格子)当然,最直接的想法是用搜索,挨个试一遍就OK了.
这也是种方法,如果加上动态规划,也是可行的算法.不过这里我没用这种方法,而是采用图论算法中已有的用于计算一个图中任意两点最短路径的经典算法--Floyd-Warshall算法.
我们可以将棋盘的64个格子看成64个节点,其中两个节点中存在一条边相连当且仅当骑士可以直接从其中的一个节点跳到另一个节点.这样骑士从棋盘某点到另一点需要移动的最少次数就转化为计算这个图中两个节点的最短路问题.至于Floyd-Warshall算法我就不多说了,随便baidu一下就知道.
剩下的问题就好办了,下面是我写的JAVA代码:
java 代码
-
-
-
-
-
-
-
-
- import
java.util.Scanner;
- public
class
Main{
-
public
static
void
main(String[] args){
- Scanner scan =
new
Scanner(System.in);
-
int
n =scan.nextInt();
-
int
[][] pos =
new
int
[n][
2
];
-
for
(
int
index =
0
;index<n;index ++){
- pos[index][
0
] =scan.nextInt();
- pos[index][
1
] =scan.nextInt();
- }
- ResultInf result =
new
Knight().solve(pos);
- System.out.print(result.x +
" "
+result.y +
" "
+result.days);
- }
- }
-
- class
Knight{
-
private
static
final
int
DEFAULT_SIZE =
8
;
-
-
private
int
boardSize;
-
-
-
private
int
[][] dist;
-
-
-
-
-
public
Knight(
int
boardSize){
-
this
.boardSize =boardSize;
- initDist();
- }
-
public
Knight(){
-
this
(DEFAULT_SIZE);
- }
-
-
-
-
-
-
public
ResultInf solve(
int
[][] pos){
-
if
(pos ==
null
||pos.length ==
0
|| pos[
0
].length !=
2
)
throw
new
IllegalArgumentException();
-
int
location =
0
,days =Integer.MAX_VALUE,allDays =
0
;
-
for
(
int
n =
0
;n<boardSize*boardSize;n ++){
-
int
max =
0
,sum =
0
;
-
for
(
int
index =
0
;index<pos.length;index ++){
-
int
dis = dist[n][pos[index][
0
]+pos[index][
1
]*boardSize];
- sum += dis;
-
if
(max<dis) max =dis;
- }
-
if
(days>max ||(days==max&&allDays>sum)){
- days =max;
- allDays =sum;
- location =n;
- }
- }
-
return
new
ResultInf(location%boardSize,location/boardSize,days);
- }
-
-
-
-
private
void
initDist(){
-
int
count =boardSize*boardSize;
- dist =
new
int
[count][count];
-
for
(
int
n =
0
;n<count;n++)
-
for
(
int
m =
0
;m<count;m++)
-
if
(m!=n) dist[m][n] = isConnect(m%boardSize,m/boardSize,n%boardSize,n/boardSize)?
1
: Integer.MAX_VALUE;
-
-
for
(
int
k =
0
;k<count;k++)
-
for
(
int
n =
0
;n<count;n++)
-
for
(
int
m =
0
;m<count;m++)
-
if
(dist[n][k]<Integer.MAX_VALUE&&dist[k][m]<Integer.MAX_VALUE&&
- dist[n][k]+dist[k][m] <dist[n][m])
- dist[n][m] =dist[n][k] +dist[k][m];
- }
-
-
-
-
private
boolean
isConnect(
int
x1,
int
y1,
int
x2,
int
y2){
-
return
(x1!=x2&&y1!=y2&&Math.abs(x1-x2)+Math.abs(y1-y2)==
3
);
- }
- }
-
-
-
-
- class
ResultInf{
-
public
int
x,y,days;
-
public
ResultInf(
int
x,
int
y,
int
days){
-
this
.x =x;
-
this
.y =y;
-
this
.days =days;
- }
- }
这个是C++版:
cpp 代码
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- #include<iostream>
- #define X(n) ((n)&7)
- #define Y(n) ((n)>>3)
- #define P(x,y) ((x)+((y)<<3))
- #define ABS(x) ((x)>=0?(x):-(x))
-
-
- const
int
SIZE = 8;
-
-
- const
int
INFINITY = 2*SIZE*SIZE;
-
-
-
- int
dest[SIZE*SIZE][SIZE*SIZE];
-
-
-
-
- bool
connected(
int
m,
int
n){
-
int
x1 =X(m), y1 =Y(m);
-
int
x2 =X(n), y2 =Y(n);
-
return
( (ABS(x1-x2)==2&&ABS(y1-y2)==1)||
- (ABS(x1-x2)==1&&ABS(y1-y2)==2)
- );
- }
-
-
-
-
- void
init(){
-
-
-
for
(
int
m =0;m< SIZE*SIZE; m++)
-
for
(
int
n =0;n< SIZE*SIZE; n++)
-
if
(m == n) dest[m][n] = 0;
-
else
dest[m][n] = connected(m,n)? 1: INFINITY;
-
-
-
for
(
int
k=0;k< SIZE*SIZE; k++)
-
for
(
int
m=0;m< SIZE*SIZE; m++)
-
for
(
int
n=0;n< SIZE*SIZE; n++)
-
if
(dest[m][n] >dest[m][k]+dest[k][n])
- dest[m][n] =dest[m][k]+dest[k][n];
- }
-
- int
main(){
- init();
-
int
size;
- std::cin>>size;
-
int
*pos =
new
int
[size];
-
for
(
int
i =0;i<size;i++){
-
int
x,y;
- std::cin>>x>>y;
- pos[i] =P(x,y);
- }
-
int
days =INFINITY,allDays,location;
-
for
(
int
m =0;m<SIZE*SIZE;m++){
-
int
max =0,sum =0;
-
for
(
int
k =0;k<size;k++){
- sum += dest[m][pos[k]];
-
if
(dest[m][pos[k]] >max) max =dest[m][pos[k]];
- }
-
if
(max<days ||(max ==days&&sum<allDays) ){
- days =max;
- allDays =sum;
- location =m;
- }
- }
-
delete
[] pos;
- std::cout<<X(location)<<
" "
<<Y(location)<<
" "
<<days;
-
return
0;
- }
分享到:
- 2007-09-16 00:42
- 浏览 3181
- 评论(2)
- 论坛回复 / 浏览 (2 / 4084)
- 查看更多
相关推荐
第9期的智慧擂台题目文件,无疑是为程序员们提供了一个提升技能、检验自身技术水平的平台。这次的主题聚焦在了技术文档的编写、程序员的基本素养以及通过实际题目来锻炼和展示程序员的解决问题能力。 技术文档是...
9期的算法擂台栏目聚焦于“骑士聚会”问题,这是一个涉及算法设计与实现的经典挑战。这个挑战源自于数学游戏,通常与图论或组合优化相关,旨在模拟中世纪骑士在棋盘上的排列方式。 "骑士聚会"问题来源于国际象棋,...
《程序员编程艺术:面试和算法心得》是一本深入探讨编程面试和算法的书籍,主要针对的是准备面试的程序员,特别是那些关注技术深度和广度,以及如何在面试中展现出自己能力的开发者。这本书可能涵盖了从基础数据结构...
程序员实用算法+源码,本书一共七个部分全部下载才可正常解压
• 第六章 海量数据处理 o 6.0 本章导读 o 6.1 关联式容器 o 6.2 分而治之 o 6.3 simhash 算法 o 6.4 外排序 o 6.5 MapReduce o 6.6 多层划分 o 6.7 Bitmap o 6.8 Bloom filter o 6.9 Trie 树 o 6.10 数据库 o 6.11 ...
总之,《程序员代码面试指南》是一本全面且深入的资源,它不仅提供了大量的代码示例,还涵盖了理论知识和实践经验,对于希望提升自己算法能力、准备IT名企面试的程序员来说,是一本不可多得的宝典。
A*搜索算法是一种在图中寻找最短路径的算法,它结合了最佳优先搜索和Dijkstra算法的优点,通过评估函数来估算从当前节点到目标节点的代价,从而决定下一个访问的节点。A*算法广泛应用于路径查找和图遍历问题,尤其是...
《2009年程序员杂志第九期》是程序员们获取技术资讯、学习新知的重要参考资料。这期杂志可能涵盖了当年的热门技术趋势、编程语言的最新发展、软件工程的实践与创新、以及针对初级和高级程序员的职业发展建议等多个...
在IT行业中,算法是程序员解决问题的关键工具,它们是编程的基础,能够帮助我们高效地处理数据和执行任务。本文档集合中的四个PHP文档深入探讨了程序员应掌握的一些经典算法,这对于提升编程技能至关重要。 首先,...
在IT行业中,算法是程序员的核心技能之一,它们是解决问题和设计高效程序的基础。"程序员实用算法.zip"这个压缩包很可能包含了一系列与编程相关的算法实现、解释或案例,旨在帮助程序员提升这方面的能力。以下是对...
程序员06第9期 免分
《程序员的算法趣题》是一本专门为IT从业者和有志于进入这个领域的学习者准备的算法书籍。它通过一系列有趣且富有挑战性的题目,旨在帮助读者深入理解和掌握计算机科学中的核心算法,提升解决实际问题的能力。这本书...
数据结构与算法是计算机科学的基础组成部分,对于程序员而言,掌握这些知识对于提升编程能力、解决实际问题以及提高软件开发效率至关重要。数据结构是组织和存储数据的方式,它决定了数据的存取效率和应用范围。而算...
程序员实用算法源码兼容VS2008及更高级的版本。在VS2008中可以直接运行,在VS2010中需先进行转换才能运行。 每个项目文件中,具体参数如何设置,是可以从源码的main函数中获得的,具体可以查看main函数中形如“...
《程序员算法趣题——随书源码》是一个与算法相关的学习资源,包含了增井敏克著作《程序员算法趣题》中的实例代码。增井敏克是算法领域知名的专家,他的书籍通常深入浅出,旨在帮助程序员提升算法思维和解决实际问题...
2006程序员第九期
【标题】"程序员06第2期" 涉及的是一期专门针对程序员的杂志或期刊,这通常包含了丰富的IT技术文章、行业动态、编程技巧、软件开发实践等内容。"06第2期"表明这是该系列的第六个年份的第二期,可能包含了当年最前沿...
《程序员实用算法》这本书主要涵盖了计算机科学中程序员经常会遇到的各种算法,这些算法是解决实际问题、优化程序性能的关键。在编程领域,算法就如同工具箱中的各种工具,它们可以帮助程序员高效地处理数据,解决...
《程序员实用算法书中的源码》是一本专为程序员设计的算法书籍,旨在提升程序员在实际工作中应用算法的能力。该书由(美)Andrew Binstock和John Rex合作撰写,并由陈宗斌等人翻译成中文。书中涵盖了一系列精选的...
在IT行业中,算法是程序员的核心技能之一,它们是解决问题和设计高效程序的基石。"程序员必知必会经典算法"这个主题涵盖了编程领域中的重要概念,包括基础算法和数据结构,这些都是C、C++等语言中不可或缺的部分。...