骑士聚会(《程序员》的算法擂台)
|
snowind9
2007-09-06
在8×8的棋盘上分布着n个骑士,他们想约在某一个格中聚会。骑士每天可以像国际象棋中的马那样移动一次,可以从中间向8个方向移动,请你计算n个骑士的最早聚会地点和要走多少天,要求尽早聚会,且n个人走的总步数最少,先到聚会地点的骑士可以不再移动等待其他的骑士。
从键盘输入n(0<n<=64),然后一次输入n个其实的初始位置xi,yi(0<=xi,y<=7)。屏幕输出以空格分割的三个数,分别为聚会的点(x,y) 以及要走的天数。 ○ ○ ○ ○ ◎ ○ ○ ○ ○ 骑士走法(中间为起始位置,空为走到位置) |
|
|
snowind9
2007-09-06
我不会,做不出来。暂时没有答案。你们研究算法的做做
|
|
|
leon_a
2007-09-06
点集类
package convex;
import queue.Queue;
import java.util.ArrayList;
import java.util.List;
import time.MethodTimeProxy;
public class Point {
public int x, y;
private boolean[][] flg = new boolean[8][8];
private int[][] shortPath = new int[8][8];
public int distanceSq(Point p1, Point p2) {
djkst(p1, p2);
return shortPath[p2.x][p2.y];
}
//迪杰科斯特最短路径
private void djkst(Point p1, Point p2) {
Queue<Point> queue = new Queue<Point>();
flg[p1.x][p1.y] = true;
queue.addQueue(p1);
while (!queue.isEmpty() && !queue.front().equals(p2)) {
Point temp = queue.front();
queue.deleteQueue();
List<Point> list = getList(temp);
int i = 0;
while (i < list.size()) {
Point w = list.get(i);
if (!flg[w.x][w.y]) {
shortPath[w.x][w.y] = shortPath[temp.x][temp.y] + 1;
queue.addQueue(w);
flg[w.x][w.y] = true;
}
i++;
}
}
}
//可行步数集
private static List<Point> getList(Point point) {
List<Point> list = new ArrayList<Point>();
if (point.x + 2 <= 7 && point.y + 1 <= 7) {
list.add(new Point(point.x + 2, point.y + 1));
}
if (point.x - 2 >= 0 && point.y - 1 >= 0) {
list.add(new Point(point.x - 2, point.y - 1));
}
if (point.x + 1 <= 7 && point.y + 2 <= 7) {
list.add(new Point(point.x + 1, point.y + 2));
}
if (point.x - 1 >= 0 && point.y - 2 >= 0) {
list.add(new Point(point.x - 1, point.y - 2));
}
if (point.x + 2 <= 7 && point.y - 1 >= 0) {
list.add(new Point(point.x + 2, point.y - 1));
}
if (point.x - 2 >= 0 && point.y + 1 <= 7) {
list.add(new Point(point.x - 2, point.y + 1));
}
if (point.x + 1 <= 7 && point.y - 2 >= 0) {
list.add(new Point(point.x + 1, point.y - 2));
}
if (point.x - 1 >= 0 && point.y + 2 <= 7) {
list.add(new Point(point.x - 1, point.y + 2));
}
return list;
}
public Point() {
}
public Point(int x, int y) {
if (x > 7 || y > 7) {
throw new RuntimeException("out of matrix");
}
this.x = x;
this.y = y;
}
public String toString() {
return "x=" + x + ",y=" + y;
}
public static void main(String[] args) {
Point p1 = new Point(3, 3);
Point p2 = new Point(0, 0);
MethodTimeProxy proxy = new MethodTimeProxy();
Point p = (Point) proxy.MethodTimeFactory(Point.class);
int cc = p.distanceSq(p1, p2);
System.out.println(cc);
}
public boolean equals(Point otherPoint) {
if (otherPoint == null) {
return false;
} else {
if (this.x == otherPoint.x && this.y == otherPoint.y) {
return true;
}
}
return false;
}
}
算法类
package convex;
import convex.Point;
public class Algo {
public static int[] method(Point[] points, Point[] matrix, int i) {
int maxDay = 0;
int distance = 0;
for (int j = 0; j < points.length; j++) {
int day = new Point().distanceSq(points[j], matrix[i]);
distance += day;
if (day > maxDay) {
maxDay = day;
}
}
return new int[]{maxDay,distance};
}
public static void main(String[] args) {
Point[] matrix = new Point[64];
int k = 0;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
matrix[k++] = new Point(i, j);
}
}
Point[] points = matrix;
int minDay = 999999999;
int minDistance = 999999999;
int flg = 0;
for (int i = 0; i < 64; i++) {
int[] result = Algo.method(points, matrix, i);
if (minDay > result[0]) {
minDay = result[0];
minDistance = result[1];
flg = i;
} else if(minDay == result[0]) {
if(minDistance > result[1]) {
minDistance = result[1];
flg = i;
}
}
}
System.out.println("min x,y=" + matrix[flg]);
System.out.println("minDay=" + minDay);
System.out.println("minDistance=" + minDistance);
}
}
我自己写的辅助类,一个队列(写图算法时做的)
package queue;
public class Queue<E> {
public GraphNode first;
public GraphNode last;
public int count;
public void addQueue(E info) {
GraphNode node = new GraphNode();
node.info = info;
if(first == null) {
first = node;
last = node;
} else {
last.link = node;
last = last.link;
}
count++;
}
public void deleteQueue() {
if(first == null) {
throw new RuntimeException("empty queue!");
} else {
first = first.link;
count--;
}
}
public boolean isEmpty() {
return count == 0;
}
public E front() {
if(first == null) {
throw new RuntimeException("empty queue!");
}
return (E)first.info;
}
public E back() {
if(last == null) {
throw new RuntimeException("empty queue!");
}
return (E)last.info;
}
}
当然还少不了一个节点
package graph;
/**
* @author B.Chen
*
*/
public class GraphNode {
/**
* 下一节点引用
*/
public GraphNode link;
/**
* 值
*/
public Object info;
}
8×8矩阵耗时8秒左右,完整算法,做了一点优化 |
|
|
leon_a
2007-09-06
我自己进行了一点优化,进行了一些减支之后,运行时间缩短到4秒左右time=4188ms
其中Point类里增加的main函数,大家可以来查看2点之间需要的步数,欢迎指正。期待优化 |
|
|
snowind9
2007-09-06
最严重的错误是 人家说的是骑士,要按照骑士的步伐来走,相差一格要走很多歩,不是距离最短就走的天数最少,他们是国际象棋的马,不是国际象棋的王。
还有就是不推荐穷举发。没有性能可言。 |
|
|
snowind9
2007-09-06
正确性和性能一个都不能少。
|
|
|
snowind9
2007-09-06
计算距离的算法应该相应的改改,然后这个穷举就差不多成立了。然后按照64个骑士测一下,看看性能。
|
|
|
xufei0110
2007-09-06
靠 你们一天都干吗 整出个这么难的题来折磨自己 我工作几个月了 没有碰过算法
|
|
|
snowind9
2007-09-06
算法就是为了让自己不麻木。做对日做久了就麻木了。
|
|
|
Spike
2007-09-06
snowind9 写道 算法就是为了让自己不麻木。做对日做久了就麻木了。
同感同感 |

