[Vicious--算法] 骑士聚会(《程序员》的算法擂台)

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 写道
算法就是为了让自己不麻木。做对日做久了就麻木了。

同感同感
Global site tag (gtag.js) - Google Analytics