《程序员》2007第九期之算法擂台

原题: 在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 代码
  1. /**  
  2.    &#Main.java  
  3.    <程序员>2007第九期算法擂台之JAVA代码  
  4.    注: 该问题的解未必唯一,但根据问题需要,只给出一个解  
  5.    另: 经测试,运行1000次new Knight()大约耗时6000毫秒  
  6.    @author Eastsun  
  7.    @version 1.0 2007/9/3  
  8. */   
  9. import  java.util.Scanner;   
  10. public   class  Main{   
  11.      public   static   void  main(String[] args){   
  12.         Scanner scan = new  Scanner(System.in);   
  13.          int  n =scan.nextInt();   
  14.          int [][] pos = new   int [n][ 2 ];   
  15.          for ( int  index = 0 ;index<n;index ++){   
  16.             pos[index][ 0 ] =scan.nextInt();   
  17.             pos[index][ 1 ] =scan.nextInt();   
  18.         }   
  19.         ResultInf result = new  Knight().solve(pos);   
  20.         System.out.print(result.x + " "  +result.y + " "  +result.days);   
  21.     }   
  22. }   
  23.   
  24. class  Knight{   
  25.      private   static   final   int  DEFAULT_SIZE =  8 ;   
  26.        
  27.      private   int  boardSize;   
  28.        
  29.      //dis[i][j]表示骑士从棋盘上位置i到j所需的最少步数,其中位置i对于棋盘坐标(i%boardSize,i/boardSize)   
  30.      private   int [][] dist;   
  31.      /**  
  32.        Knight的构造函数  
  33.        @param boardSize 棋盘的大小,默认值为8  
  34.     */   
  35.      public  Knight( int  boardSize){   
  36.          this .boardSize =boardSize;   
  37.         initDist();   
  38.     }   
  39.      public  Knight(){   
  40.          this (DEFAULT_SIZE);   
  41.     }   
  42.      /**  
  43.        根据骑士的位置求解  
  44.        @param pos 一个int[][2]数组,第k个骑士的位置为(pos[k][0],pos[k][1])  
  45.        @return result 该问题的解,注意:当result.days ==Integer.MAX_VALUE的时候说明这些骑士永远不可能聚在一起  
  46.     */   
  47.      public  ResultInf solve( int [][] pos){   
  48.          if (pos == null ||pos.length == 0 || pos[ 0 ].length != 2 )  throw   new  IllegalArgumentException();   
  49.          int  location = 0 ,days =Integer.MAX_VALUE,allDays = 0 ;   
  50.          for ( int  n = 0 ;n<boardSize*boardSize;n ++){   
  51.              int  max = 0 ,sum = 0 ;   
  52.              for ( int  index = 0 ;index<pos.length;index ++){   
  53.                  int  dis = dist[n][pos[index][ 0 ]+pos[index][ 1 ]*boardSize];   
  54.                 sum += dis;   
  55.                  if (max<dis) max =dis;   
  56.             }   
  57.              if (days>max ||(days==max&&allDays>sum)){   
  58.                 days =max;   
  59.                 allDays =sum;   
  60.                 location =n;   
  61.             }   
  62.         }   
  63.          return   new  ResultInf(location%boardSize,location/boardSize,days);   
  64.     }   
  65.      /**  
  66.        使用Floyd-Warshall算法计算dist的值,时间复杂度O(boardSize^6)  
  67.     */   
  68.      private   void  initDist(){   
  69.          int  count =boardSize*boardSize;   
  70.         dist = new   int [count][count];   
  71.          for ( int  n = 0 ;n<count;n++)   
  72.              for ( int  m = 0 ;m<count;m++)   
  73.                  if (m!=n) dist[m][n] = isConnect(m%boardSize,m/boardSize,n%boardSize,n/boardSize)?  1 : Integer.MAX_VALUE;   
  74.                    
  75.          for ( int  k = 0 ;k<count;k++)   
  76.              for ( int  n = 0 ;n<count;n++)   
  77.                  for ( int  m = 0 ;m<count;m++)   
  78.                      if (dist[n][k]<Integer.MAX_VALUE&&dist[k][m]<Integer.MAX_VALUE&&   
  79.                           dist[n][k]+dist[k][m] <dist[n][m])   
  80.                               dist[n][m] =dist[n][k] +dist[k][m];   
  81.     }   
  82.      /**  
  83.        判断(x1,y1)与(x2,y2)是否直接可到  
  84.     */   
  85.      private   boolean  isConnect( int  x1, int  y1, int  x2, int  y2){   
  86.          return  (x1!=x2&&y1!=y2&&Math.abs(x1-x2)+Math.abs(y1-y2)== 3 );   
  87.     }   
  88. }   
  89.   
  90. /**  
  91.    一个用于保存求解信息的类  
  92. */   
  93. class  ResultInf{   
  94.      public   int  x,y,days;   
  95.      public  ResultInf( int  x, int  y, int  days){   
  96.          this .x =x;   
  97.          this .y =y;   
  98.          this .days =days;   
  99.     }   
  100. }  

 

 

这个是C++版:

cpp 代码
  1. /**  
  2.   注:: 对原题中  
  3.         "请你计算n个骑士的最早聚会地点和要走多少天.要求尽早聚会,且n个人走的总步数最少"  
  4.        感觉有歧义,不知道是"最早聚会"条件优先还是"走的总步数最少"条件优先.  
  5.        本代码中采用的是先考虑"最早聚会",其次考虑"走的总步数最少".另: 解未必唯一  
  6. **  
  7.   &#Together.cpp  
  8.   算法描叙:  
  9.       将棋盘上的SIZE*SIZE个位置看成SIZE*SIZE个节点,并且两个节点存在连线当且仅当马能够在这两个位置直接走动.  
  10.       定义两个节点m,n的距离dest[m][n]为马从m走到n所需的最少步数  
  11.       这样,可以通过Floyd-Warshall算法得到dest.  
  12.       算法的时间复杂度为O(SIZE^6),空间复杂度为O(SIZE^4)  
  13.       余略  
  14.    @author Eastsun  
  15.    @version 1.0 2007/9/3  
  16. */   
  17. #include<iostream>   
  18. #define X(n) ((n)&7)   
  19. #define Y(n) ((n)>>3)   
  20. #define P(x,y) ((x)+((y)<<3))   
  21. #define ABS(x) ((x)>=0?(x):-(x))   
  22.   
  23. // 棋盘的大小   
  24. const   int  SIZE = 8;   
  25.   
  26. // 一个用于表示"无限大"的数,只要比棋盘上任意两点的距离都大就OK   
  27. const   int  INFINITY = 2*SIZE*SIZE;   
  28.   
  29. // dest[m][n] 表示棋盘上m点到n点的距离   
  30. // 其中 棋盘上坐标为(x,y)的点对应dest中 x+y*8 的点   
  31. int  dest[SIZE*SIZE][SIZE*SIZE];   
  32.   
  33. /**  
  34.    点m与点n在棋盘上是否直接可到  
  35. */   
  36. bool  connected( int  m, int  n){   
  37.      int  x1 =X(m), y1 =Y(m);   
  38.      int  x2 =X(n), y2 =Y(n);   
  39.      return  ( (ABS(x1-x2)==2&&ABS(y1-y2)==1)||   
  40.              (ABS(x1-x2)==1&&ABS(y1-y2)==2)    
  41.             );   
  42. }   
  43.   
  44. /**  
  45.   计算dest的值  
  46. */   
  47. void  init(){   
  48.        
  49.      //初始化dest,将dest[n][n]设为0,可以直接到达的设为1,其余设为INFINITY   
  50.      for ( int  m =0;m< SIZE*SIZE; m++)   
  51.          for ( int  n =0;n< SIZE*SIZE; n++)   
  52.              if (m == n)   dest[m][n] = 0;   
  53.              else          dest[m][n] = connected(m,n)? 1: INFINITY;   
  54.                    
  55.      //计算dest   
  56.      for ( int  k=0;k< SIZE*SIZE; k++)   
  57.          for ( int  m=0;m< SIZE*SIZE; m++)   
  58.              for ( int  n=0;n< SIZE*SIZE; n++)   
  59.                  if (dest[m][n] >dest[m][k]+dest[k][n])   
  60.                     dest[m][n] =dest[m][k]+dest[k][n];   
  61. }   
  62.   
  63. int  main(){   
  64.     init();   
  65.      int  size;   
  66.     std::cin>>size;   
  67.      int  *pos = new   int [size];   
  68.      for ( int  i =0;i<size;i++){   
  69.          int  x,y;   
  70.         std::cin>>x>>y;   
  71.         pos[i] =P(x,y);   
  72.     }   
  73.      int  days =INFINITY,allDays,location;   
  74.      for ( int  m =0;m<SIZE*SIZE;m++){   
  75.          int  max =0,sum =0;   
  76.          for ( int  k =0;k<size;k++){   
  77.             sum += dest[m][pos[k]];   
  78.              if (dest[m][pos[k]] >max) max =dest[m][pos[k]];   
  79.         }   
  80.          if (max<days ||(max ==days&&sum<allDays) ){   
  81.             days =max;   
  82.             allDays =sum;   
  83.             location   =m;   
  84.         }   
  85.     }   
  86.      delete [] pos;   
  87.     std::cout<<X(location)<< " " <<Y(location)<< " " <<days;   
  88.      return  0;   
  89. }   

#10028. 「一本通 1.4 例 3」Knight Moves(利用queue队列写广搜)(queue写广搜模板) Knight Moves 题目描述 编写一个程序,计算一个骑士从棋盘上的一个格子到另一个格子所需的最小步数。骑士一步可以移动到的位置由下图给出。 输入格式 第一行给出骑士的数量 n。 在接下来的 3n 行中,每 3 行描述了一个骑士。其中, 第一行一个整数 L 表示棋盘的大小,整个棋盘大小为 L*L; 第二行和第三行分别包含一对整数(x,y) ,表示骑士的起始点和终点。假设对于每一个骑士,起始点和终点均合理。 输出格式 对每一个骑士,输出一行一个整数表示需要移动的最小步数。如果起始点和终点相同,则输出0 阅读详情

相关推荐

五子棋框架-打擂专用

五子棋框架-打擂专用

Knight Moves POJ 1915(bfs)

编写一个程序,计算一个骑士从棋盘上的一个格子到另一个格子所需的最小步数。骑士一步可以移动到的位置由下图给出。一匹马走日字,给定起点和终点,问所需要的最小步骤。一般问到最值很明显就是bfs了,图太大了也不适合dfs。vec是向量,保存了一个点能跳到的坐标。保存从起点开始能第一次跳到的坐标的所有情况,并且刷新这些点的访问情况,访问过的、出界的不访问,按照队列结构依次往下重复直到到达目标点为止。...

Crushlikearush的博客 424

【初阶】手把手教你轻松上手Denodo | 连接数据库并创建基本视图 (二)

在本教程的第二部分,我们将涵盖:连接到数据库,与创建基本视图。

Denodo的博客 1113

选择排序

选择排序

弱爆了的雪饼的博客 589

coze开发-5、给智能体添加“技能”

中间编排与技能组件 中间编排的定义 中间编排是指在智能体的构建过程中,使用一些工具对智能体进行协调和管理。通过这些工具,我们能够更好地实现智能体在特定业务场景中的应用。

andyyah晓波的博客 528

全网最全的AItium Designer 16下载资源与安装步骤

Altium Designer 除了全面继承包括Protel 99SE、Protel DXP在内的先前一系列版本的功能和优点外,还增加了许多改进和很多高端功能。该平台拓宽了板级设计的传统界面,全面集成了FPGA设计功能和SOPC设计实现功能,从而允许工程设计人员能将系统设计中的FPGA与PCB设计及嵌入式设计集成在一起。...

WQ的博客 1万+

用队列解决骑士移动问题

一问题描述 计算骑士从一个位置移动到另外一个位置所需的最少移动次数。骑士移动规则如下图。 输入:测试用例包含3行。 第1行:表示棋盘的长度L,范围在 [4,300],棋盘的大小为L *L。 第2行:骑士在棋盘的开始位置。 第3行:骑士在棋盘的结束位置。 输出:输出骑士从起点移动到终点所需的最少移动次数。如果起点和终点相等,则移动次数为零。 下面是三组测试用例的结果。 输入 输出 8 (0,0) (7,0) ...

实践求真知 1408

《QMT量化实战系列》支持自定义筛选与排序的多因子策略,实测年化收益超100%

【QMT量化实战系列】推出《支持自定义筛选与排序的多因子策略》,通过Tushare获取38个核心因子数据,实现股票多维筛选(剔除ST股、次新股及特定板块)。策略创新性地采用多因子加权排名机制,通过(股票数-排名+1)/股票数*100的算法计算各因子得分,支持自定义权重组合。该策略提供完整代码及详细注释,涵盖数据获取、因子筛选、权重排序等核心环节,帮助用户构建个性化量化模型。系列内容每月更新1-2期,由浅入深讲解QMT平台实战应用。

qq_46262068的博客 1256

Knight Moves(信息学奥赛一本通-T1450)

【题目描述】 编写一个程序,计算一个骑士从棋盘上的一个格子到另一个格子所需的最小步数。骑士一步可以移动到的位置由下图给出。 【输入】 第一行给出骑士的数量 n。 在接下来的 3n 行中,每 3 行描述了一个骑士。其中,第一行一个整数 L 表示棋盘的大小,整个棋盘大小为 L×L; 第二行和第三行分别包含一对整数 (x,y),表示骑士的起始点和终点。假设对于每一个骑士,起始点和终点均合...

Alex_McAvoy的博客 1875

STM32 野火MINI 用FontCvtST.exe 生成.c文件 写汉字到文本框 按钮上

STM32 野火MINI 用FontCvtST.exe 生成.c文件 写汉字到文本框 按钮上 参考了好多大神博客,自己写的过程中发现,还有些小细节。 一、打开Notepad写需要的字 另存为 UTF-16LE 也就是Unicode。 二、打开FontCvtST转 删掉所有字 读入test.txt里的字 选择刚才的test.txt 另存为.c文件 改个英文名 复制到RTOS的例程文件夹下 三、打开GUIBuilder 画一个这样的 保存之前要注意路径配置要在当前位置,否则存不上 生成的D

weixin_41376117的博客 1938

三相直流无刷电机(带HALL传感器)BLDC控制一

本案例选择TIM0的CH0/CH1/CH2三个通道接入三路原始hall输出信号。三路TIM_CHx(48)通过配置存入到NIP寄存器(new input pattern,3 bits)内。未完待续。

m0_69929716的博客 407

第1部分 基础算法(提高篇)--第4章 广搜的优化技巧-1450:【例 3】Knight Moves

1450:【例 3】Knight Moves 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 1170 通过数: 406 【题目描述】 原题来自:POJ 1915 编写一个程序,计算一个骑士从棋盘上的一个格子到另一个格子所需的最小步数。骑士一步可以移动到的位置由下图给出。 【输入】 第一行给出骑士的数量 n。 在接下来的 3n 行中,每 3 行描述了一个骑士。其中, 第一行一个整数 L 表示棋盘的大小,整个棋盘大小为 L×L; 第二行和第三行分别包含一对整数 (

zqhf123的博客 1018

KT148A语音芯片SOP外挂功放芯片8002D的说明_V1

KT148A语音芯片内置8欧姆0.5W的功放,所以一般的应用场景,播放一些提示音音量是足够的。但是有的需求还需要驱动更大的扬声器,实现更大的播放音量,这里我们给出解决方案。KT148A+HAA8002D的组合

qyvhome的博客 2152

java擂台比较,[分享]《程序员》2007第九期算法擂台之JAVA代码

[分享]《程序员》2007第九期算法擂台之JAVA代码[url=http://eastsun.javaeye.com/blog/124477]本题JAVA及C++代码下载[/url]原题:在8*8的棋盘上分布着n个骑士,他们想约在某一格中聚会.骑士每天可以像国际象棋中的马那样移动一次.请你计算n个骑士的最早聚会地点和要走多少天.要求尽早聚会,且n个人走的总步数最少,先到的骑士可以不再移动等待其它骑...

weixin_26801149的博客 164

088、多摄像头跨镜目标追踪 ID 频繁切换?ReID 特征 + 轨迹关联 + 时间约束方案

文章摘要:本文针对多摄像头跨镜目标追踪中ID频繁切换的问题,提出了一种结合ReID特征、轨迹关联和时间约束的综合解决方案。作者分析了ID切换的三个主要原因:ReID特征不稳定、轨迹关联依赖最近邻匹配以及忽略时间约束。通过改进ReID特征提取(多层特征融合)、引入轨迹预测(卡尔曼滤波)和添加时间窗口约束,成功将ID切换率从35%降至3%以下。文章详细分享了实现细节和踩坑经验,为跨摄像头目标追踪提供了实用优化思路。

ai技术增长的博客 169

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

《程序员》2007年第九期算法擂台——骑士聚会

问题:    在8×8的棋盘上分布着n个骑士,他们想约在某一格的中聚会,骑士每天可以像国际象棋中的马那样移动一次,如下图所示,可以从中间向8个方向移动,请你计算n个骑士的最早聚会地点和要走多少天。要求尽早聚会,且n个人走的总步数最少,先到聚会地点的骑士可以不再移动等候其他骑士。    从键盘输入n(0  因为水平还是有限,只是按照最原始的方法来解决这个问题。  首先解决数据结构,将每个格子

757

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

《程序员》算法擂台之骑士聚会问题

ProgramerChina的专栏 857

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

java打擂台算法,打擂台算法.ppt

打擂台算法打擂台算法适用于: 求若干个数中的最大/小值 例题 找两数中的较大者 a=val(inputbox("请输入第一个数")) b=val(inputbox("请输入第二个数")) if a>=b then max=a else max=b endif print max 双分支的写法 (非打擂台的算法) 例题 找两数中的较大者 输入a 输...

weixin_33855603的博客 962

用Java-数组 “打擂”

java l--数组擂台赛

不会飞的小飞侠24 1271

Knight Moves

题目描述 原题来自:POJ 1915 编写一个程序,计算一个骑士从棋盘上的一个格子到另一个格子所需的最小步数。骑士一步可以移动到的位置由下图给出。 输入 第一行给出骑士的数量n。 在接下来的3n行中,每3行描述了一个骑士。其中, 第一行一个整数L表示棋盘的大小,整个棋盘大小为L×L; 第二行和第三行分别包含一对整数(x,y),表示骑士的起始点和终点。假设对于每一个骑士,起...

算法小猪的博客 5041

骑士问题

题目 题目描述 小明是一名出色的棋手,声称没有人能像他那样快速地把骑士从一个位置移到另一个位置,你能打败他吗?编写一个程序,计算一个骑士从棋盘上的一个格子到另一个格子所需的最小步数。骑士一步可以移动到的位置由下图给出。 输入 第一行给出骑士的数量 n。对于每一个骑士都有3行,第一行一个整数 L 表示棋盘的大小(4≤L≤300),整个棋盘大小为 L×L...

weixin_30699741的博客 577

#10028. 「一本通 1.4 例 3」Knight Moves

编写一个程序,计算一个骑士从棋盘上的一个格子到另一个格子所需的最小步数。骑士一步可以移动到的位置由下图给出。

ipalg666的博客 215

骑士

题目描述 骑士的行走方式类似于象棋中的马,现在给你一个任务,计算骑士从一点到另一点所需的最少步数。 输入 第一行给出骑士的数量n。对于每一个骑士都有3行,第一行一个整数L,表示棋盘的大小(4<=L<=300),整个棋盘大小为LxL(坐标范围为0...L);第二行和第三行分别包含一对整数(xy),表示骑士的起始点和终点。假设,对于每一个骑士起始点和终点均合理。 输出 对每一个骑...

泪、无痕的博客 491

算法训练营 训练 骑士移动(队列)

队列queue 队列只允许从队尾入队、从队头出队,不允许再中间位置插入和删除,不支持数组表示法和随机访问。使用queue时需要引入头文件#include<queue>。 queue<int> q:创建一个空队q,数据类型为int push(x):x入队 pop():出队 front():取队头(未出队) empty():判断队列是否为空,若为空,则返回true size():求队列大小,返回队列中的元素个数。 题目描述 写程序,计算骑士从一个位置移动到另一个位置所需的最少移动次数

qq_20144897的博客 1014

java打擂台排序_C++擂台法排序

#includeusingnamespacestd;voidSort1(inta1[],intn){inti,j;inttemp,max;for(i=0;i#include using namespace std;void Sort1(int a1[],int n){int i,j;int temp,max;for(i=0;imax=i;for(j=0;jif(a1[max] < a1[j]...

weixin_30983563的博客 959
上一篇: 《程序员》2007第八期之算法擂台
下一篇: Java SE 6 Update N Early Access is now available!
JavaSxy
博客等级 码龄21年 1粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值