您的位置:首页 > 编程语言 > Java开发

蚂蚁爬杆问题的java实现

2009-10-11 00:30 148 查看
题目描述:
有一根27厘米的细木杆,在第3厘米、7厘米、11厘米、17厘米、23厘米这五个位置上各有一只蚂蚁。木杆很细,不能同时通过一只蚂蚁。开始时,蚂蚁的头朝左还是朝右是任意的,它们只会朝前走或调头,但不会后退。当任意两只蚂蚁碰头时,两只蚂蚁会同时调头朝反方向走。假设蚂蚁们每秒钟可以走一厘米的距离。编写程序,求所有蚂蚁都离开木杆的最小时间和最大时间。

/**
* Filename:    com.yangphere.demo.AntWalker.java
* Description:  题目描述: 有一根27厘米的细木杆, 在第3厘米、7厘米、11厘米、17厘米、23厘米这五个位置上各有一只蚂蚁。 木杆很细,不能同时通过一只蚂蚁。
* 开始时,蚂蚁的头朝左还是朝右是任意的,它们只会朝前走或调头,但不会后退。 当任意两只蚂蚁碰头时,两只蚂蚁会同时调头朝反方向走。
* 假设蚂蚁们每秒钟可以走一厘米的距离。 编写程序,求所有蚂蚁都离开木杆的最小时间和最大时间。
* Copyright:   Copyright (c)2009
* Company:     yangphere
* @author:     yangphere
* @version:    1.0
* Create at:   2009-6-28
*
* Modification History:
* Date			Author		Version		Description
* ------------------------------------------------------------------
* 2009-6-28	yangphere	1.0			1.0 Version
*/
package com.yangphere.demo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* 配合逻辑分析给出一种简单的实现方式
* 其中有个很重要的原则是:当任意两只蚂蚁碰头时,两只蚂蚁会同时调头朝反方向走,其实和假设两只蚂蚁之间可以无障碍穿过时是一样的(忽略蚂蚁自身的长度)。
*
* @author yangphere
*
*/
public class AntWalker {

/**
* 细木杆长度
*/
private static final int TOTAL_LENGTH = 27;

/**
* 蚂蚁的位置
*/
private static final List<Integer> ANT_PER_POSITION = new ArrayList<Integer>();

/**
* 初始化蚂蚁位置
*/
static {
ANT_PER_POSITION.add(3);
ANT_PER_POSITION.add(7);
ANT_PER_POSITION.add(11);
ANT_PER_POSITION.add(17);
ANT_PER_POSITION.add(23);
}

/**
*
* @author yangphere 2009-6-28
* @param args
*/
public static void main(String[] args) {
if (!check()) {
System.out.println("参数错误!");
} else {
System.out.println("最短时间是:" + getMinTime() + "秒");
System.out.println("最长时间是:" + getMaxTime() + "秒");
}
}

/**
* 获得最长时间 根据那个原则,无需关心蚂蚁碰撞的问题,最长时间就是所有蚂蚁中距细杆一端最长的那只蚂蚁的爬完时间
*
* @author yangphere 2009-6-29
* @return
*/
private static int getMaxTime() {
// 对蚂蚁位置排序
Collections.sort(ANT_PER_POSITION);
// 获得最靠两端的蚂蚁
int oneSide = ANT_PER_POSITION.get(0);
int anotherSide = ANT_PER_POSITION.get(ANT_PER_POSITION.size() - 1);

// 获得一只蚂蚁距两端最长的距离
int oneMax = (oneSide > (TOTAL_LENGTH - oneSide)) ? oneSide
: TOTAL_LENGTH - oneSide;
int antherMax = (anotherSide > (TOTAL_LENGTH - anotherSide)) ? anotherSide
: TOTAL_LENGTH - anotherSide;

return oneMax > antherMax ? oneMax : antherMax;
}

/**
* 获得最短时间 根据那个原则,最短时间就是距细杆中间最近的那只蚂蚁爬完细杆最短的那端所花的时间
*
* @author yangphere 2009-6-29
* @return
*/
private static int getMinTime() {

// 蚂蚁距一端的距离
int oneSide = getNearCenterAnt();

// 蚂蚁距另一段的距离
int anotherSide = TOTAL_LENGTH - oneSide;

return oneSide < anotherSide ? oneSide : anotherSide;
}

/**
* 获得最接近细杆中间的蚂蚁
*
* @author yangphere 2009-6-29
* @return
*/
private static int getNearCenterAnt() {
// 中间位置
double center = TOTAL_LENGTH / 2.0;
// 离中间最近的蚂蚁的位置
int antNearCenter = 0;

Map<Integer, Double> map = new HashMap<Integer, Double>();

double antNearPosition = center - ANT_PER_POSITION.get(0);
for (Integer ant : ANT_PER_POSITION) {
antNearPosition = antNearPosition < Math.abs(center - ant) ? antNearPosition
: Math.abs(center - ant);

map.put(ant, Math.abs(center - ant));
}

Set<Integer> set = map.keySet();
for (Iterator iterator = set.iterator(); iterator.hasNext();) {
Integer key = (Integer) iterator.next();
if (antNearPosition == map.get(key)) {
antNearCenter = key;
break;
}
}

return antNearCenter;
}

/**
* 检查参数的正确性
*
* @author yangphere 2009-6-29
* @return
*/
private static boolean check() {
if (TOTAL_LENGTH <= 0) {
return false;
} else if (ANT_PER_POSITION.size() <= 0) {
return false;
}

// 站在杆外
for (Integer ant : ANT_PER_POSITION) {

if (ant <= 0) {
return false;
} else if (ant > TOTAL_LENGTH) {
return false;
}
}

return true;
}

}


2.0

public class Ant {

private static int LONG = 27;

private int[] a = { 3, 7, 11, 17, 23 };

private int min = 0, max = 0;

public void gogogo() {
for (int i = 0; i < a.length; i++) {
min = Math.max(min, Math.min(a[i], LONG - a[i]));
max = Math.max(max, Math.max(a[i], LONG - a[i]));
}
}

public int getMax() {
return max;
}

public int getMin() {
return min;
}

public static void main(String[] args) {

Ant client = new Ant();
client.gogogo();
System.out.println(client.getMax());
System.out.println(client.getMin());
}
}


3.0

package com.leochan;

import java.util.LinkedList;

public class RecursionAntWalker {

public static int spendTime = 0;

public static int totalLength = 27;

public static void main(String[] args) {

recursionTest();

}

// 递归计算32种不同情况下所需要的时间。
private static void recursionTest() {
int count = 0;
for (int d1 = -1; d1 <= 1; d1 += 2) {
for (int d2 = -1; d2 <= 1; d2 += 2) {
for (int d3 = -1; d3 <= 1; d3 += 2) {
for (int d4 = -1; d4 <= 1; d4 += 2) {
for (int d5 = -1; d5 <= 1; d5 += 2) {
count++;
spendTime = 0;
Ant a = new Ant(3);
Ant b = new Ant(7);
Ant c = new Ant(11);
Ant d = new Ant(17);
Ant e = new Ant(23);
a.direction = d1;
b.direction = d2;
c.direction = d3;
d.direction = d4;
e.direction = d5;

LinkedList<Ant> testCase = new LinkedList<Ant>();

testCase.add(a);
testCase.add(b);
testCase.add(c);
testCase.add(d);
testCase.add(e);

System.out.print("count=" + count + " d1=" + d1
+ " d2=" + d2 + " d3=" + d3 + " d4=" + d4
+ " d5=" + d5);
System.out
.println("  getTime=" + getTime(testCase));
}
}
}
}
}
}

// 递归计算每种组合需要的时间
public static int getTime(LinkedList<Ant> antList) {

int len = antList.size();

// 如果antList里没有蚂蚁,直接返回spendTime
if (len == 0)
return spendTime;

// 如果antList里只有1只蚂蚁,让这种蚂蚁一直走下去,直到它达到边界。
// 在spendTime和这只蚂蚁所走过的distance中取最大值做为最终花费的时间
if (len == 1) {
Ant onlyAnt = antList.getFirst();
onlyAnt.keepWalking();
return (spendTime > onlyAnt.distance) ? spendTime
: onlyAnt.distance;
}

// 如果antList里的第一只蚂蚁的运动方向为负方向,即-1,
// 就重新计算spendTime,并且将这只蚂蚁移出list,递归去getTime
if (!antList.getFirst().positiveDirect()) {
Ant currentAnt = antList.removeFirst();
spendTime = (currentAnt.position > spendTime) ? currentAnt.position
+ currentAnt.distance : spendTime;
}

// 如果antList里最后一只蚂蚁的方向为正方向,即1
// 就重新计算spendTime,并且将这只蚂蚁移出list,递归去getTime
else if (antList.getLast().positiveDirect()) {
Ant currentAnt = antList.removeLast();
int needToGo = totalLength - currentAnt.position;
spendTime = (needToGo > spendTime) ? needToGo + currentAnt.distance
: spendTime;
}

// 其他情况下,让所有的蚂蚁按方向走一步,并判断有没有2只蚂蚁的位置重合,
// 如果有重合,就让对应的2只蚂蚁转向。
else {
for (int i = 0; i < len; i++) {
antList.get(i).walking();
if (!antList.get(i).positiveDirect()) {
if (antList.get(i).checkPosition(antList.get(i - 1))) {
antList.get(i).changedirect();
antList.get(i - 1).changedirect();
}
}
}
}

return getTime(antList);
}
}

// 蚂蚁类
class Ant {

public int distance = 0; // 走过的距离,数值上等于时间
public int position; // 当前的位置,在0-27之间

public int direction = -1; // 运动的方向,-1表示向左,1表示向右

public Ant(int position) {
this.position = position;
}

// 用来判断运动方向是否为正方向
public boolean positiveDirect() {
return direction > 0;
}

// 如果位置在0-27之间,让蚂蚁一直行走
public void keepWalking() {
while (this.position > 0
&& this.position < RecursionAntWalker.totalLength)
this.walking();
}

// 检查2只蚂蚁的位置是否相同
public boolean checkPosition(Ant ant) {
return this.position == ant.position;
}

// 让当前的蚂蚁转向
public void changedirect() {
direction = -direction;
}

// 让蚂蚁按照自己的方向走1步,即经历单位时间1.
public void walking() {
distance += 1;
position += direction;
}
}


4.0

package com.leochan;

import java.util.LinkedList;

public class RecursionAntWalker {

public static int spendTime = 0;

public static int totalLength = 27;

public static void main(String[] args) {

recursionTest();

}

// 递归计算32种不同情况下所需要的时间。
private static void recursionTest() {
int count = 0;
for (int d1 = -1; d1 <= 1; d1 += 2) {
for (int d2 = -1; d2 <= 1; d2 += 2) {
for (int d3 = -1; d3 <= 1; d3 += 2) {
for (int d4 = -1; d4 <= 1; d4 += 2) {
for (int d5 = -1; d5 <= 1; d5 += 2) {
count++;
spendTime = 0;
Ant a = new Ant(3);
Ant b = new Ant(7);
Ant c = new Ant(11);
Ant d = new Ant(17);
Ant e = new Ant(23);
a.direction = d1;
b.direction = d2;
c.direction = d3;
d.direction = d4;
e.direction = d5;

LinkedList<Ant> testCase = new LinkedList<Ant>();

testCase.add(a);
testCase.add(b);
testCase.add(c);
testCase.add(d);
testCase.add(e);

System.out.print("count=" + count + " d1=" + d1
+ " d2=" + d2 + " d3=" + d3 + " d4=" + d4
+ " d5=" + d5);
System.out
.println("  getTime=" + getTime(testCase));
}
}
}
}
}
}

// 递归计算每种组合需要的时间
public static int getTime(LinkedList<Ant> antList) {

int len = antList.size();

// 如果antList里没有蚂蚁,直接返回spendTime
if (len == 0)
return spendTime;

// 如果antList里只有1只蚂蚁,让这种蚂蚁一直走下去,直到它达到边界。
// 在spendTime和这只蚂蚁所走过的distance中取最大值做为最终花费的时间
if (len == 1) {
Ant onlyAnt = antList.getFirst();
onlyAnt.keepWalking();
return (spendTime > onlyAnt.distance) ? spendTime
: onlyAnt.distance;
}

// 如果antList里的第一只蚂蚁的运动方向为负方向,即-1,
// 就重新计算spendTime,并且将这只蚂蚁移出list,递归去getTime
if (!antList.getFirst().positiveDirect()) {
Ant currentAnt = antList.removeFirst();
spendTime = (currentAnt.position > spendTime) ? currentAnt.position
+ currentAnt.distance : spendTime;
}

// 如果antList里最后一只蚂蚁的方向为正方向,即1
// 就重新计算spendTime,并且将这只蚂蚁移出list,递归去getTime
else if (antList.getLast().positiveDirect()) {
Ant currentAnt = antList.removeLast();
int needToGo = totalLength - currentAnt.position;
spendTime = (needToGo > spendTime) ? needToGo + currentAnt.distance
: spendTime;
}

// 其他情况下,让所有的蚂蚁按方向走一步,并判断有没有2只蚂蚁的位置重合,
// 如果有重合,就让对应的2只蚂蚁转向。
else {
for (int i = 0; i < len; i++) {
antList.get(i).walking();
if (!antList.get(i).positiveDirect()) {
if (antList.get(i).checkPosition(antList.get(i - 1))) {
antList.get(i).changedirect();
antList.get(i - 1).changedirect();
}
}
}
}

return getTime(antList);
}
}

// 蚂蚁类
class Ant {

public int distance = 0; // 走过的距离,数值上等于时间
public int position; // 当前的位置,在0-27之间

public int direction = -1; // 运动的方向,-1表示向左,1表示向右

public Ant(int position) {
this.position = position;
}

// 用来判断运动方向是否为正方向
public boolean positiveDirect() {
return direction > 0;
}

// 如果位置在0-27之间,让蚂蚁一直行走
public void keepWalking() {
while (this.position > 0
&& this.position < RecursionAntWalker.totalLength)
this.walking();
}

// 检查2只蚂蚁的位置是否相同
public boolean checkPosition(Ant ant) {
return this.position == ant.position;
}

// 让当前的蚂蚁转向
public void changedirect() {
direction = -direction;
}

// 让蚂蚁按照自己的方向走1步,即经历单位时间1.
public void walking() {
distance += 1;
position += direction;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: