一道面试题,求各位给下思路

Sally_simple 2014-01-03 07:25:40
加精
接到一道面试题,由于本人技术有限,想的我头发都快白了,还没有动手写。
在这请求大家的帮助,说说大致的思路。万分感谢。

要求大致是这样
实现一个商店收银模拟系统, 计算所有顾客结账时间需要多久。用OOD实现。先进先出原则
1 有1-n个收银台,分为普通收银台,和培训收银台。 区别:假设顾客有一个商品,在普通收银台每个商品需要1min, 而在培训收银台需要2min。n个收银台中当且仅有一个培训收银台。期中培训收银台的编号是所有收银台中编号最大的。比如两个收银台,则培训收银台是 #2.

2 顾客分为两种 A 和 B。
A顾客排队总是选择 人数最少的队。 B顾客排队总是选择 队末尾的那个人商品个数越少的队,不关心队有多少人,除了最后一个人,其他人的商品数。

3 模拟系统的起始时间是 t = 0

4. 如果两个顾客的在同一时间到达 收银台, 商品数少的顾客先结账, 如果商品数一样,则A类顾客先于B类。

Example
A:顾客类型, 第一个int是到达收银台的时间, 第二个是商品的个数。

A 1 5
B 2 1
A 3 5
B 5 3
A 8 2

• t=0 : 两个收银台,培训收银台是 2号
• t=1 : Customer #1 (type A) 到达, 5个商品,去一号收银台
• t=2 : Customer #2 (type B) 到达, 1 个商品, 去2号收银台。
• t=3 : Customer #3 (type A) 到达, 5个商品, 因为是A类顾客,去1号收银台。
• t=4 : Customer #2 离开2号收银台。
• t=5 : Customer #4 (type B) 到达, 3个商品。2号是空的, 所以去2号收银台。
• t=6 : Customer #1 离开,1号服务Custom #3.
• t=8 : Customer #5 (type A) 到达, 2个商品。 因为两个收银台都有一个人,就去了一号收银台,在Custom #3 后面
• t=11 : Customer #3 离开。 1号收银台服务5号顾客。
• t=11 : Customer #4 离开2号收银台。
• t=13 : Customer #5 离开1号收银台

output: 完成时间13mins。

我的思路是 用queue去实现。具体的希望大家给些思路

谢谢大家能把题读完。
请大家说说思路吧,还有大致有几个类和方法,改如何实现。
120分奉上
...全文
9054 155 打赏 收藏 转发到动态 举报
写回复
用AI写文章
155 条回复
切换为时间正序
请发表友善的回复…
发表回复
lym406365619 2014-02-07
  • 打赏
  • 举报
回复
mark一下!!!
另一花生 2014-01-30
  • 打赏
  • 举报
回复
引用 12 楼 bbos1994 的回复:
帮顶,怎么感觉这是奥数题,,,,好烧脑
我也觉得是、、、
lnkToKing 2014-01-24
  • 打赏
  • 举报
回复

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 收银台
 * @author Administrator
 */
class Charge {
    int number; // 编号
    int type = 0; // 类型,0普通收银台,1培训收银台
    List<Client> queue = new ArrayList<Client>(); // 排队的顾客
    int lastGoodsNum = 0; // 最后一个顾客的商品数
    private int nextTime = 0; // 下个顾客收费开始的时间

    public Charge(int number) {
	this.number = number;
    }

    /**
     * 顾客加入队列
     * 
     * @param client
     */
    public void addClient(Client client) {
	queue.add(client);
	lastGoodsNum = client.goodsNum;
    }

    /**
     * 到下一个顾客收费
     */
    void nextClient() {
	if (ChargeSystem.time == nextTime) { // 当前顾客收费完成,从队列中移除
	    if (queue.size() > 0) {
		Client c = queue.get(0);
		String chargeType = type == 0 ? "普通" : "培训";
		System.out.print(chargeType + "收银机" + number + "完成一个" + c.type
			+ "类顾客收费,");
		int s = c.goodsNum * (type == 0 ? 1 : 2);
		System.out.println("商品数:" + c.goodsNum + ",花费时间:" + s);
		queue.remove(0);
		if (queue.size() == 0)
		    lastGoodsNum = 0;
	    }
	}
	if (ChargeSystem.time >= nextTime) {
	    if (queue.size() > 0) { // 计算下一顾客需要的收费时长
		// 培训机每件商品收费时候2分钟,普通机1分钟
		nextTime = queue.get(0).goodsNum * (type == 0 ? 1 : 2);
		nextTime += ChargeSystem.time;
	    }
	}
    }
}

/**
 * 顾客抽象类
 * 考虑顾客以后的扩展,不同顾客选择的收银台方式不台,所以抽象出一个类
 * @author Administrator
 */
abstract class Client{
    String type;  //顾客类型
    int arrival; // 到达时间
    int goodsNum; // 商品数量

    public Client(String type, int arrival, int goodsNum) {
	this.type = type;
	this.arrival = arrival;
	this.goodsNum = goodsNum;
    }

    /**
     * 根据顾客自己的喜好加入收银机的队列
     */
    public abstract void joinQueue(List<Charge> charges);
    /**
     * 顾客选择收银台优先权
     */
    public int compareTo(Client c){
	if(goodsNum != c.goodsNum) 
	    return goodsNum - c.goodsNum; //商品数量不一样的,数量少优先
	return type.compareTo(c.type); //否则A类顾客优先
    }
    /**
     * 创建顾客
     */
    public static Client createClinet(String type, int arrival, int goodsNum){
	if("A".equals(type)){
	    return new ClientA(arrival, goodsNum);
	}else if("B".equals(type)){
	    return new ClientB(arrival, goodsNum);
	}
	return null;
    }
}
/**
 * A类顾客
 */
class ClientA extends Client {
    public ClientA(int arrival, int goodsNum) {
	super("A", arrival, goodsNum);
    }

    @Override
    public void joinQueue(List<Charge> charges) {
	int index = 0;
	if (charges.size() > 1) {
	    for (int i = 0; i < charges.size() - 1; i++) { // A顾客排队总是选择人数最少的队
		if (charges.get(i).queue.size() > charges.get(i + 1).queue.size())
		    index = i + 1;
	    }
	}
	charges.get(index).addClient(this);
	System.out.println("A("+goodsNum+")顾客加入了收银台" + charges.get(index).number + "的队列");
    }

}

/**
 * B类顾客
 */
class ClientB extends Client {
    public ClientB(int arrival, int goodsNum) {
	super("B", arrival, goodsNum);
    }

    @Override
    public void joinQueue(List<Charge> charges) {
	int index = 0;
	if (charges.size() > 1) {
	    for (int i = 0; i < charges.size() - 1; i++) { // B顾客排队总是选择 队末尾的那个人商品个数越少的队
		if (charges.get(i).lastGoodsNum == 0) {
		    index = i;
		    break;
		} else if (charges.get(i + 1).lastGoodsNum == 0) {
		    index = i + 1;
		    break;
		} else {
		    if (charges.get(i).lastGoodsNum > charges.get(i + 1).lastGoodsNum)
			index = i + 1;
		}
	    }
	}
	charges.get(index).addClient(this);
	System.out.println("B("+goodsNum+")顾客加入了收银台" + charges.get(index).number + "的队列");
    }

}
/**
 * @描述:实现一个商店收银
 * @Author lnk
 * @timer 2014年1月24日 上午11:53:35
 */
public class ChargeSystem {
    static int time;  //时间
    private List<Charge> charges;  //收银机队列
    private List<Client> clients; //顾客们
    
    /**
     * 初始化收银台和顾客
     */
    public void init(){
	initCharges(2);
	initClients();
    }
    /**
     * 初始化收银台
     * @param num
     */
    private void initCharges(int num){
	charges = new ArrayList<Charge>();
	while(--num >= 0){
	    charges.add(0, new Charge(num + 1));
	}
	if(charges.size() > 0)
	    charges.get(charges.size() - 1).type = 1;  //最后一台为培训机
    }
    /**
     * 初始化顾客
     */
    private void initClients(){
	clients = new ArrayList<Client>();
	clients.add(Client.createClinet("A",1,5));
	clients.add(Client.createClinet("B",2,1));
	clients.add(Client.createClinet("A",3,5));
	clients.add(Client.createClinet("B",5,3));
	clients.add(Client.createClinet("A",8,2));
	clients.add(Client.createClinet("B",3,2));
	clients.add(Client.createClinet("A",5,3));
    }
    /**
     * 顾客选择收银台
     * @param list
     */
    public void selectCharge(List<Client> list){
	//按顾客优先权排序
	Collections.sort(list, new Comparator<Client>() {
	    @Override
	    public int compare(Client o1, Client o2) {
		return o1.compareTo(o2);
	    }
	});
	for (Client client : list) {
	    client.joinQueue(charges);
	}
    }
    /**
     * 打印收银的顾客队列
     */
    public void display(){
	for (Charge charge : charges) {
	    System.out.print("收银机"+charge.number+"的队列:");
	    for (Client client : charge.queue) {
		System.out.print(client.type + "(" + client.goodsNum + ") ");
	    }
	    System.out.println();
	}
	System.out.println();
    }
    
    public static void main(String[] arg){
	ChargeSystem system = new ChargeSystem();
	system.init();
	time = 0;
	int startTime = -1;
	boolean quit = true;
	do{
	    System.out.println("时间:"+time);
	    
	  //找出到达收银台的顾客
	    List<Client> list = new ArrayList<Client>();  
	    for (int i = system.clients.size() - 1; i >= 0; i--) {
		if(system.clients.get(i).arrival == time){
		    if(startTime == -1) startTime = time;  //记录第一个顾客到达时间
		    list.add(system.clients.get(i));
		    system.clients.remove(i);
		}
	    }
	    //顾客按优先权选择收银台
	    system.selectCharge(list);
	    
	    boolean isAllClear = true;
	    for(Charge c : system.charges){
		c.nextClient();
		if(c.queue.size() > 0) isAllClear = false;
	    }
	    system.display();
	    time++;
	    //如果所有客户已经去结算同时所以收银台已结算完成就退出程序
	    quit = !(isAllClear && system.clients.size() == 0);
	}while(quit);{
	System.out.println("完成,时间:" + (time - startTime));
    }
}
}

时间:0 收银机1的队列: 收银机2的队列: 时间:1 A(5)顾客加入了收银机1的队列 收银机1的队列:A(5) 收银机2的队列: 时间:2 B(1)顾客加入了收银机2的队列 收银机1的队列:A(5) 收银机2的队列:B(1) 时间:3 B(2)顾客加入了收银机2的队列 A(5)顾客加入了收银机1的队列 收银机1的队列:A(5) A(5) 收银机2的队列:B(1) B(2) 时间:4 培训收银机2完成一个B类顾客收费,商品数:1,花费时间:2 收银机1的队列:A(5) A(5) 收银机2的队列:B(2) 时间:5 A(3)顾客加入了收银机2的队列 B(3)顾客加入了收银机2的队列 收银机1的队列:A(5) A(5) 收银机2的队列:B(2) A(3) B(3) 时间:6 普通收银机1完成一个A类顾客收费,商品数:5,花费时间:5 收银机1的队列:A(5) 收银机2的队列:B(2) A(3) B(3) 时间:7 收银机1的队列:A(5) 收银机2的队列:B(2) A(3) B(3) 时间:8 A(2)顾客加入了收银机1的队列 培训收银机2完成一个B类顾客收费,商品数:2,花费时间:4 收银机1的队列:A(5) A(2) 收银机2的队列:A(3) B(3) 时间:9 收银机1的队列:A(5) A(2) 收银机2的队列:A(3) B(3) 时间:10 收银机1的队列:A(5) A(2) 收银机2的队列:A(3) B(3) 时间:11 普通收银机1完成一个A类顾客收费,商品数:5,花费时间:5 收银机1的队列:A(2) 收银机2的队列:A(3) B(3) 时间:12 收银机1的队列:A(2) 收银机2的队列:A(3) B(3) 时间:13 普通收银机1完成一个A类顾客收费,商品数:2,花费时间:2 收银机1的队列: 收银机2的队列:A(3) B(3) 时间:14 培训收银机2完成一个A类顾客收费,商品数:3,花费时间:6 收银机1的队列: 收银机2的队列:B(3) 时间:15 收银机1的队列: 收银机2的队列:B(3) 时间:16 收银机1的队列: 收银机2的队列:B(3) 时间:17 收银机1的队列: 收银机2的队列:B(3) 时间:18 收银机1的队列: 收银机2的队列:B(3) 时间:19 收银机1的队列: 收银机2的队列:B(3) 时间:20 培训收银机2完成一个B类顾客收费,商品数:3,花费时间:6 收银机1的队列: 收银机2的队列: 完成,时间:20
henrydee1 2014-01-20
  • 打赏
  • 举报
回复
不错,想法很好。比数据结构书里的可复杂了,比面向对象书里的也现实多了
blackkettle 2014-01-20
  • 打赏
  • 举报
回复
大赞!
xiao_mu_mu 2014-01-20
  • 打赏
  • 举报
回复
初级学员,学习学习~
liu912239196 2014-01-18
  • 打赏
  • 举报
回复
另外,少写点help类,ood什么的算式要求吧,当然如果觉得麻烦也可以show一下模式
liu912239196 2014-01-18
  • 打赏
  • 举报
回复
四种对象 营业员,面板,队列,客户 1.类营业员,随着时间的增加进行work,可改变面板值中最少客户的信息 2.面板对象,可以为静态,2个属性,1个最少人数队列编号,1个最后一个人最少货物编号 3.队列对象,拥有所有的营业员,营业员的改变也通过这个对象,且客户的添加页通过此对象,是营业员与客户的容器对象,可以改变最后一个最少货物面板的编号 4.客户对象,客户到会会参考慢板值以选则编号 对于不同的客户/营业员可以用子类也可以用type字段,根据要求最好是子类 营业员 num;//编号 List<Customer>;//排队人数 power;//能量值,每分钟1增长什么的,也可以加个工作能力之类的,用子类实现,可以省掉,在work方法中直接写 work(int min); 队列拥 List ;//管理营业员 addCus(Customer cus);添加客户,记得修改面板 客户拥 choose();//选择 至于main,最好是for循环,循环一次代表过去1min
弗朗德 2014-01-17
  • 打赏
  • 举报
回复
这种题明显是算法题非线程使用的
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;


public class Main {

	
	@SuppressWarnings("resource")
	public static void main(String[] args) {
		//获取控制台输入
		//Sample:
		//2
		//A 1 5
		//B 2 1
		//A 3 5
		//B 5 3
		//A 8 2
        //ctrl + z
		Scanner scanner = new Scanner(System.in);
		int count = scanner.nextInt();
		World world = new World(count);
		int num = 1;
		List<Customer> list = new ArrayList<Customer>();
		while(scanner.hasNext()){
			Customer command = Customer.getCustomer(scanner.next().charAt(0), scanner.nextInt(), scanner.nextInt(), num++);
			list.add(command);
		}
		Collections.sort(list);  //排序,按到达时间,类型,携带商品来排
		
		world.setCustomers(list);  
		System.out.println(String.format("output: 完成时间%1$smins。", world.run()));
	}
	
}
import java.util.List;


/**
 * 用户接口,定义用户的操作
 */
public abstract class Customer implements Comparable<Customer>{

	/**
	 * 客户的商品数,初始值为0
	 */
	private int goods;
	
	/**
	 * 顾客的到达时间,初始值为0
	 */
	private int time;
	
	/**
	 * 客户所站的收银台,初始化为null
	 */
	private Checkstand checkstand;
	
	private String name;
	
	/**
	 * 构造方法
	 * @param goods 商品数
	 * @param time 到达时间
	 */
	protected Customer(int goods, int time, int name){
		this.goods = goods;
		this.time = time;
		this.name = "#" + name;
	}
	
	/**
	 * 获取真实顾客的实例,由type决定真实顾客是哪种类型
	 * @param type 顾客类型
	 * @param goods 商品数
	 * @param time 到达时间
	 * @return 不同顾客类型的实例
	 */
	public static Customer getCustomer(char type,int time,int goods ,int name){
		switch(type){
		case 'A':case 'a':
			return new CustomerA(goods, time, name);
		case 'B':case 'b':
			return new CustomerB(goods, time, name);
		}
		return null;
	}

	/**
	 * 商品数的getter
	 * @return 商品数
	 */
	public int getGoods() {
		return goods;
	}

	/**
	 * 商品数的setter
	 * @param goods 商品数
	 */
	public void setGoods(int goods) {
		this.goods = goods;
	}
	
	/**
	 * 顾客的到达时间的setter
	 * @return 顾客的到达时间
	 */
	public int getTime() {
		return time;
	}

	/**
	 * 顾客的到达时间的getter
	 * @param time 顾客的到达时间
	 */
	public void setTime(int time) {
		this.time = time;
	}

	/**
	 * 所属收银台的getter
	 * @return 所属收银台
	 */
	public Checkstand getCheckstand() {
		return checkstand;
	}

	/**
	 * 所属收银台的setter
	 * @param checkstand 所属收银台
	 */
	public void setCheckstand(Checkstand checkstand) {
		this.checkstand = checkstand;
		if(null!=checkstand)
			checkstand.addCustomers(this);
	}
	
	public String getName(){
		return name;
	}
	
	public int getLeaveTime(){
		return getCheckstand().getFirstLeaveTime();
	}
	
	public abstract char getType();
	
	/**
	 * 顾客的选择策略
	 * @param checkstands 收银台序列
	 */
	public abstract boolean choose(List<Checkstand> checkstands);
	

	@Override
	public int compareTo(Customer o) {
		if(time != o.time)
			return time - o.time;
		if(getType() != o.getType())
			return getType() - o.getType();
		if(goods != o.goods)
			return goods - o.goods;
		return 0;
	}
	
}
import java.util.List;

/**
 * 顾客A 
 */
public class CustomerA extends Customer {
	
	/**
	 * 构造方法
	 */
	public CustomerA(int goods, int time, int name){
		super(goods, time, name);
	}

	/**
	 * 选择站哪队,A的策略为站人少的,我想傻子都会优先站没人的吧
	 */
	@Override
	public boolean choose(List<Checkstand> checkstands) {
		int min=-1;
		Checkstand toStand = null;
		for(Checkstand checkstand:checkstands){
			int size = checkstand.getCustomers().size();
			if(size==0){
				setCheckstand(checkstand);
				return true;
			}
			if(min < 0 || min > size){
				min = size;
				toStand = checkstand;
			}
		}
		setCheckstand(toStand);
		return false;
	}

	/**
	 * 返回顾客的类型字符
	 */
	public char getType(){
		return 'A';
	}
}
import java.util.List;

/**
 * 顾客B
 */
public class CustomerB extends Customer {

	/**
	 * 构造方法
	 */
	public CustomerB(int goods, int time, int name){
		super(goods, time, name);
	}
	
	/**
	 * 顾客B的选择策略:站最后那个拿的东西少的,同样肯定站没人的队
	 */
	@Override
	public boolean choose(List<Checkstand> checkstands) {
		int min = -1;
		Checkstand toStand = null;
		for(Checkstand checkstand:checkstands){
			int size = checkstand.getCustomers().size();
			if(size==0){
				setCheckstand(checkstand);
				return true;
			}
			int count = checkstand.getGoodsOfLastCustomer();
			if(min < 0 || min > count){
				min = count;
				toStand = checkstand;
			}
		}
		setCheckstand(toStand);
		return false;
	}

	/**
	 * 返回顾客的类型字符
	 */
	public char getType(){
		return 'B';
	}
}
import java.util.LinkedList;
import java.util.Queue;

/**
 * 定义收银台的接口
 */
public class Checkstand {
	
	/**
	 * 剩余顾客的队列
	 */
	private Queue<Customer> customers;
	
	/**
	 * 最后一名顾客的商品数
	 */
	private int goodsOfLastCustomer;
	
	/**
	 * 每个商品的点算时间
	 */
	private int timeOfCounting;
	
	/**
	 * 收银台编码
	 */
	private int num;
	
	/**
	 * 该 收银台最后一次送顾客的时间
	 */
	private int lastLeaveTime;
	
	/**
	 * 构造函数,默认点算时间为1
	 */
	public Checkstand(int num){
		customers = new LinkedList<Customer>();
		timeOfCounting = 1;
		this.num = num;
	}
	
	/**
	 * 构造函数,指定点算时间
	 * @param timeOfCounting 点算时间
	 */
	public Checkstand(int timeOfCounting, int num){
		this(num);
		this.timeOfCounting = timeOfCounting;
	}

	/**
	 * 顾客队列的getter
	 * @return 顾客队列
	 */
	public Queue<Customer> getCustomers() {
		return customers;
	}

	/**
	 * 获得最后那个顾客的商品数
	 * @return 最后那个顾客的商品数
	 */
	public int getGoodsOfLastCustomer() {
		return goodsOfLastCustomer;
	}

	/**
	 * 设置最后那个顾客的商品数
	 * @param goodsOfLastCustomer 最后那个顾客的商品数
	 */
	public void setGoodsOfLastCustomer(int goodsOfLastCustomer) {
		this.goodsOfLastCustomer = goodsOfLastCustomer;
	}

	/**
	 * 添加一名顾客,同时更新最后一名顾客的商品数量
	 * @param customer 新增顾客队列
	 */
	public void addCustomers(Customer customer) {
		this.customers.add(customer);
		this.goodsOfLastCustomer = customer.getGoods();
	}
	
	public int getNum(){
		return num;
	}
	
	/**
	 * 送别顾客
	 */
	public void sendCustomer(){
		lastLeaveTime = getFirstLeaveTime();
		Customer customer = getCustomers().poll();
		if(null!=customer){
			System.out.println(String.format("t=%1$s : Customer %2$s 离开%3$s号收银台。", lastLeaveTime, customer.getName(), this.getNum()));
			
			customer.setCheckstand(null);
		}
	}
	
	/**
	 * 获得第一个顾客离开的时间
	 * @return 第一个顾客离开的时间
	 */
	public int getFirstLeaveTime(){
		Customer customer = customers.peek();
		if(null != customer && lastLeaveTime<customer.getTime()){
			lastLeaveTime = customer.getTime();
		}
		if(null != customer){
			return lastLeaveTime + customer.getGoods() * timeOfCounting;
		}
		return lastLeaveTime;
	}
}
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * 客观世界,模拟时间的流逝,顾客选择队列,顾客离开等客观现实
 */
public class World {
	
	/**
	 * 队头的顾客
	 */
	private SortedSet<Customer> customers;
	
	/**
	 * 所有顾客
	 */
	private List<Customer> allCustomer;
	
	/**
	 * 所有的收银台
	 */
	private List<Checkstand> checkstands;
	
	/**
	 * 最后一名顾客离开的时间,即处理完的时间
	 */
	private int leaveTime;
	
	/**
	 * 世界构造器,初始化世界的变量
	 * @param count 收银台的个数
	 */
	public World(int count){
		customers = new TreeSet<Customer>(new Comparator<Customer>() {
			@Override
			public int compare(Customer o1, Customer o2) {
				if(o1.getCheckstand().getFirstLeaveTime()!=o2.getCheckstand().getFirstLeaveTime())
					return o1.getCheckstand().getFirstLeaveTime() - o2.getCheckstand().getFirstLeaveTime();
				else
					return o1.getCheckstand().getNum() - o2.getCheckstand().getNum();
			}
		});
		checkstands = new ArrayList<Checkstand> ();
		for(int i=0;i<count-1;i++){
			checkstands.add(new Checkstand(i+1));
		}
		checkstands.add(new Checkstand(2, count));
		System.out.println(String.format("t=0: %1$s个收银台, 培训收银台是%1$s号", count));
	}
	
	/**
	 * 新来一位顾客
	 * @param customer 添加新顾客
	 */
	private void customerIncome(Customer customer){
		//新增顾客时先看在这名顾客到达前是否有离开收银台的顾客
		while(!customers.isEmpty() && customers.first().getCheckstand().getFirstLeaveTime() <= customer.getTime()){
			sendCustomer();
		}
		if(customer.choose(checkstands)){
			customers.add(customer);
		}
		System.out.println(String.format("t=%1$s : Customer %2$s %5$s 到达, %3$s个商品,去%4$s号收银台", customer.getTime(), customer.getName(), customer.getGoods(), customer.getCheckstand().getNum(), customer.getType()));
	}
	
	/**
	 * 计算完成的时间
	 * @return
	 */
	public int run(){
		for(Customer customer: allCustomer){
			customerIncome(customer);
		}
		while(!customers.isEmpty()){
			sendCustomer();
		}
		return leaveTime;
	}
	
	/**
	 * 送离顾客,每当一位顾客离开,调用一次
	 */
	private void sendCustomer(){
		Customer toSend = customers.first();
		Checkstand checkstand = toSend.getCheckstand();
		leaveTime = checkstand.getFirstLeaveTime();
		customers.remove(toSend);
		checkstand.sendCustomer();
		if(null != checkstand.getCustomers().peek()){
			customers.add(checkstand.getCustomers().peek());
		}
	}

	/**
	 * 将排好序的顾客设置好
	 * @param customers 已排序的顾客列表
	 */
	public void setCustomers(List<Customer> customers){
		this.allCustomer = customers;
	}
}
本身很简单的题目,不过因为要求OOD,所以代码有点长,不过OOD也有好处,假设需要增加顾客类型或者收银台类型,可以很容易拓展
铅笔️ 2014-01-16
  • 打赏
  • 举报
回复
学习一下
zilang625 2014-01-16
  • 打赏
  • 举报
回复
我说下我的想法,其实最关键的地方你要找到,客人的人数不固定,但是收银台固定,你要做的是判断是那个收银台的最后一个人。第一种最后一个人买的东西最少,第二种情况人最少,你判断对了切入点,什么都好做
richard_1015 2014-01-16
  • 打赏
  • 举报
回复
大神不少
Zoro_年华 2014-01-15
  • 打赏
  • 举报
回复
支持~顶一下
xwj 2014-01-15
  • 打赏
  • 举报
回复
都是牛人!厉害
Lavener 2014-01-15
  • 打赏
  • 举报
回复
求鉴定正确性,不过我觉得这个题目在运行的时候有随机性啊! Customer.java
package com.armslee.test.model;

import java.io.Serializable;


public class Customer implements Serializable{
	
	private static final long serialVersionUID = 5934650144340059385L;
	private String type;
	private int arriveTime;
	private int goodsCount;
	/**
	 * 需要为这个顾客服务的总时间
	 */
	private int needHandleTime = -1;
	
	public Customer() {
	}
	
	public Customer(String type,int t,int c){
		this.type = type;
		this.arriveTime = t;
		this.goodsCount = c;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public int getArriveTime() {
		return arriveTime;
	}

	public void setArriveTime(int arriveTime) {
		this.arriveTime = arriveTime;
	}

	public int getGoodsCount() {
		return goodsCount;
	}

	public void setGoodsCount(int goodsCount) {
		this.goodsCount = goodsCount;
	}

	public int getNeedHandleTime() {
		return needHandleTime;
	}

	public void setNeedHandleTime(int needHandleTime) {
		this.needHandleTime = needHandleTime;
	}


}
CashierDesk.java
package com.armslee.test.body;

import java.io.Serializable;
import java.util.Iterator;
import java.util.LinkedList;

import com.armslee.test.model.Customer;

public class CashierDesk implements Serializable{
	
	private static final long serialVersionUID = 4398752666847665193L;
	
	/**
	 * 每一个收银台用一个链表来存放顾客,
	 * 每一个顾客都放在一个链表中,
	 * 并且相同时间到的顾客放在同一个链表中
	 */
	private LinkedList<LinkedList<Customer>> cashierDesk;
	
	/**
	 * 每个收银台的顾客数量
	 */
	private int cashierDeskCount;
	
	/**
	 * 最后一次添加顾客到此收银台的时间
	 */
	private int lastAddTime = 0;
	
	/**
	 * 初始化收银台
	 */
	public CashierDesk(){
		cashierDesk = new LinkedList<LinkedList<Customer>>();
	}
	
	/**
	 * 添加顾客到此收银台队尾
	 * 
	 * @param c 顾客信息
	 * @return
	 */
	public boolean addCustomer(Customer c){
		LinkedList<Customer> linkedList = this.cashierDesk.peekLast();
		if(null != linkedList && linkedList.peekLast().getArriveTime() == c.getArriveTime()){
			Iterator<Customer> ite = linkedList.iterator();
			int index = 0;
			while(ite.hasNext()){
				Customer cite = ite.next();
				if(cite.getGoodsCount()>c.getGoodsCount()){//时间一样,商品数少的优先
					break;
				}
				index ++;
			}
			if(index == linkedList.size()){//时间和商品数都一样,A类优先B类
				index = 0;
				if("B".equals(c.getType())){//B类直接放到最后面
					linkedList.addLast(c);
				}else{
					Iterator<Customer> ite2 = linkedList.iterator();
					while(ite2.hasNext()){
						Customer cite = ite2.next();
						if("A".equals(cite.getType())){//时间一样,商品数少的优先
							index ++;
						}else{
							break;
						}
						
					}
				}
			}
		    linkedList.add(index, c);
		}else{
			LinkedList<Customer> temp = new LinkedList<Customer>();
			temp.add(c);
			this.cashierDesk.add(temp);
		}
		this.cashierDeskCount++;
		this.lastAddTime = c.getArriveTime();
		return true;
	}
	
	/**
	 * 获取该收银台最后一个顾客信息
	 * 
	 * @return
	 */
	public Customer peekLast(){
		LinkedList<Customer> linkedList = this.cashierDesk.peekLast();
		if(null != linkedList && !linkedList.isEmpty()){
			return linkedList.peekLast();
		}
		return null;
	}
	
	/**
	 * 获取该收银台第一个顾客的信息并删除顾客信息
	 * 
	 * @return
	 */
	public Customer poll(){
		LinkedList<Customer> linkedList = this.cashierDesk.peek();
		Customer c = null;
		if(null != linkedList){
			c = linkedList.poll();
		}
		cashierDeskCount--;
		if(linkedList.isEmpty()){
	    	this.cashierDesk.poll();//删除已经没有顾客的队列
	    }
		return c;
	}
	
	/**
	 * 获取该收银台第一个顾客的信息但不删除顾客信息
	 * 
	 * @return
	 */
	public Customer peek(){
		LinkedList<Customer> linkedList = this.cashierDesk.peek();
		if(null != linkedList && !linkedList.isEmpty()){
			return linkedList.peek();
		}
		return null;
	}

	public LinkedList<LinkedList<Customer>> getCashierDesk() {
		return cashierDesk;
	}

	public void setCashierDesk(LinkedList<LinkedList<Customer>> cashierDesk) {
		this.cashierDesk = cashierDesk;
	}

	public int getCashierDeskCount() {
		return cashierDeskCount;
	}

	public void setCashierDeskCount(int cashierDeskCount) {
		this.cashierDeskCount = cashierDeskCount;
	}

	public int getLastAddTime() {
		return lastAddTime;
	}

	public void setLastAddTime(int lastAddTime) {
		this.lastAddTime = lastAddTime;
	}
}
CashierDeskConfig.java
package com.armslee.test.body;

import java.util.List;

import com.armslee.test.model.Customer;

public class CashierDeskConfig {
	/**
	 * 收银台数组
	 */
	private static CashierDesk[] cashierDesk;
	
	/**
	 * 收银台数目
	 */
	private static int cashierDeskNum;
	
	/**
	 * 当前处理时间
	 */
	private static int currentTime = 0;
	
	/**
	 * 非实习收银台处理一件商品的时间
	 */
	public final static int TIME_ONE = 1;
	
	/**
	 * 实习收银台处理一件商品的时间
	 */
	public final static int TIME_TWO = 2;
	
	
	public CashierDeskConfig() {
		
	}
	
	/**
	 * 初始化收银台数组
	 * 
	 * @param deskNum
	 */
	public CashierDeskConfig(int deskNum){
		cashierDeskNum = deskNum;
		cashierDesk = new CashierDesk[cashierDeskNum];
		for(int i =0 ;i<cashierDeskNum;i++){
			cashierDesk[i] = new CashierDesk();
		}
	}
	
	/**
	 * 每来一个顾客刷新一次收银台顾客的排队情况
	 * 
	 * @return
	 */
	public void refreshCashierDesk(int arriveTime){
		
		for(int i=0;i<cashierDeskNum;i++){
				//当前刷新时刻需要处理的时间(分钟)
				int needHandleTime = arriveTime - currentTime;
				//标记是否处理完成,如果没有则继续处理
				boolean done = false;
				while(!done){
					//取出该收银台上的第一个顾客
					Customer c = cashierDesk[i].peek();
					//该收银台没有顾客,直接退出
					if(null == c){
						break;
					}
					if(c.getNeedHandleTime() < needHandleTime){//处理当前顾客需要的时间小于当前时刻需要进行处理的时间	
						cashierDesk[i].poll();
						needHandleTime -= c.getNeedHandleTime();
						//当前处理的时刻
						int nowCurrentTime = currentTime + c.getNeedHandleTime();
						Customer cc = cashierDesk[i].peek();
						if(null == cc){
							break;
						}
						//下一个顾客到达的时间在前一个顾客处理完之后
						if(cc.getArriveTime()> nowCurrentTime){
							//两个顾客到达的间隙时间超过了当前还需要处理的时间
							if((cc.getArriveTime() - nowCurrentTime) >= needHandleTime){
								done = true;
							}else{
								needHandleTime -= (cc.getArriveTime() - nowCurrentTime);
							}
						}
					}else if(c.getNeedHandleTime() == needHandleTime){
						cashierDesk[i].poll();
						done = true;
					}else if(c.getNeedHandleTime() > needHandleTime){
						c.setNeedHandleTime(c.getNeedHandleTime() - needHandleTime);
						done = true;
					}
			  }
		 }
		currentTime = arriveTime;
	}
	
	/**
	 * 
	 * 计算所有收银台在排好队并没有新的顾客加进来时完成收款的时间,选取最大值保存,将
	 * 其与排队处理时已经花费的时间就是整个收银需要的最大时间
	 * 
	 * @return
	 */
	public int calculateTime(){
		int t = 0;
		for(int i=0;i<cashierDeskNum;i++){
			int tt = 0;
			while(cashierDesk[i].getCashierDeskCount()>0){
				Customer c = cashierDesk[i].poll();
				tt += c.getNeedHandleTime();
			}
			if(tt > t){
				t = tt;
			}
		}
		return t + currentTime;
	}
	
	/**
	 * 添加顾客到收银台上
	 * 
	 * @param c
	 * @return
	 */
	public void addCustomerByList(List<Customer> c){
		for (Customer customer : c) {
			refreshCashierDesk(customer.getArriveTime());
			int index = checkCashierDesk(customer.getType());
			if(index == cashierDeskNum-1){
				customer.setNeedHandleTime(customer.getGoodsCount()*TIME_TWO);
			}else{
				customer.setNeedHandleTime(customer.getGoodsCount()*TIME_ONE);
			}
			cashierDesk[index].addCustomer(customer);
		}
	}
	
	/**
	 * 为顾客找一个合适的收银台等待付款
	 * 
	 * @param customerType
	 * @return
	 */
	private int checkCashierDesk(String customerType){
		if(cashierDesk[0].getCashierDeskCount() == 0){//第一个收银台还没有顾客
			return 0;
		}
		int index = 0;
		if("A".equals(customerType)){//A类顾客,选择人数最少的收银台
			for(int i=1;i<cashierDeskNum;i++){
				int s1 = cashierDesk[i].getCashierDeskCount();
				int s2 = cashierDesk[i-1].getCashierDeskCount();
				if(s1 == 0){//除了第一个收银台以外有一个没有顾客的收银台并且第一个收银台有顾客
					index = i;
					return index;
				}
				if( s1< s2){
					index = i;
				}
			}
		}else{//B类顾客,选择队尾顾客商品数最少的收银台
			for(int i=1;i<cashierDeskNum;i++){
				Customer c1 = cashierDesk[i].peekLast();
				Customer c2 = cashierDesk[i-1].peekLast();
				if(null == c1){//除了第一个收银台以外有一个没有顾客的收银台并且第一个收银台有顾客
					index = i;
					return index;
				}
				if(c1.getGoodsCount() < c2.getGoodsCount()){
					index = i;
				}
			}
		}
		return index;
	}
}
Cashier.java
package com.armslee.test;

import java.util.ArrayList;
import java.util.List;

import com.armslee.test.body.CashierDeskConfig;
import com.armslee.test.model.Customer;

public class Cashier {
	
	public static void main(String[] args) {
		
		CashierDeskConfig cdf = new CashierDeskConfig(2);
		Customer c1 = new Customer("A",1,3);
		Customer c2 = new Customer("B",1,5);
		Customer c3 = new Customer("A",3,1);
		Customer c4 = new Customer("B",4,1);
		Customer c5 = new Customer("A",4,1);
		List<Customer> clist = new ArrayList<Customer>();
		clist.add(c1); 
		clist.add(c2);
		clist.add(c3);
		clist.add(c4);
		clist.add(c5);
		cdf.addCustomerByList(clist);
		System.out.println("*********************************Lavender****************************");
		System.out.println("完成收银时间为:  "+cdf.calculateTime()+" mins");
		System.out.println("*********************************Lavender****************************");
		

	}

}
运行结果:

*********************************Lavender****************************
完成收银时间为:  13 mins
*********************************Lavender****************************
小错_曾经 2014-01-15
  • 打赏
  • 举报
回复
见贴必回,下手必狠。
瀚盟 2014-01-15
  • 打赏
  • 举报
回复
学习一下、、、、
yuandaopian2012 2014-01-15
  • 打赏
  • 举报
回复
顾客是另一个对象,其中包括它携带商品的数量和到达时间 www.zwjdjx.com 收银台应该把顾客组织成一个队列(用个链表就行)
早早2001 2014-01-14
  • 打赏
  • 举报
回复
好像很难的样子研究下。
丶宝物 2014-01-14
  • 打赏
  • 举报
回复
大神真多啊!!!
加载更多回复(112)
昨日,11.19,最新整理了,第61-80题,现在公布上传。 另加上之前公布的第1-60 题,在此做一次汇总上传,以飨各位。 可以这么说,绝大部分的面试题,都是这100 道题系列的翻版, 此微软等公司数据结构+算法面试100 题系列,是极具代表性的经典面试题。 而,对你更重要的是,我自个还提供了答案下载,提供思路,呵。 所以,这份资料+答案,在网上是独一无二的。 ------------------------------------ 整理资源,下载地址: 答案系列: 1.[最新答案V0.3 版]微软等数据结构+算法面试100 题[第21-40 题答案] http://download.csdn.net/source/2832862 2.[答案V0.2 版]精选微软数据结构+算法面试100 题[前20 题]--修正 http://download.csdn.net/source/2813890 //此份答案是针对最初的V0.1 版本,进行的校正与修正。 3.[答案V0.1 版]精选微软数据结构+算法面试100 题[前25 题] http://download.csdn.net/source/2796735 题目系列: 4.[第一部分]精选微软等公司数据结构+算法经典面试100 题[1-40 题] http://download.csdn.net/source/2778852 5.[第1 题-60 题汇总]微软等数据结构+算法面试100 题 http://download.csdn.net/source/2826690 更多资源,下载地址: http://v_july_v.download.csdn.net/ 若你对以上任何题目或任何答案,有任何问题,欢迎联系我: My E-mail: zhoulei0907@yahoo.cn ------------- 作者声明: 本人July 对以上公布的所有任何题目或资源享有版权。转载以上公布的任何一题, 或上传百度文库资源,请注明出处,及作者我本人。 向你的厚道致敬。谢谢。 ---July、2010 年11 月20 日。 ------------------------------------------------------ 各位,若对以上100题任何一道,或对已上传的任何一题的答案, 有任何问题,请把你的思路、想法,回复到此帖子上, 微软等100题系列,永久维护地址(2010年11.26日): http://topic.csdn.net/u/20101126/10/b4f12a00-6280-492f-b785-cb6835a63dc9.html
此为我个人搜集整理的, 精选微软等公司数据结构和算法的面试100题[前41-60题], 此绝对值得你下载收藏。 ----------------------------- 网友yui评论,真是够多的了,从此,不用再看其它面试题.... 一句话,请享用。 July、2010/11.05. ----------------------------------------------- 其它资源,下载地址: [最新整理公布][汇总II]微软等数据结构+算法面试100题[第1-80题] http://download.csdn.net/source/2846055 1.[最新答案V0.3版]微软等数据结构+算法面试100题[第21-40题答案] http://download.csdn.net/source/2832862 2.[第1题-60题汇总]微软等数据结构+算法面试100题 http://download.csdn.net/source/2826690 3.[答案V0.2版]精选微软数据结构+算法面试100题[前20题]--修正 http://download.csdn.net/source/2813890 //此份答案是针对最初的V0.1版本,进行的校正与修正。 4.[答案V0.1版]精选微软数据结构+算法面试100题[前25题] http://download.csdn.net/source/2796735 5.[第二部分]精选微软等公司结构+算法面试100题[前41-60题]: http://download.csdn.net/source/2811703 6.[第一部分]精选微软等公司数据结构+算法经典面试100题[1-40题] http://download.csdn.net/source/2778852 更多资源,下载地址: http://v_july_v.download.csdn.net/ ------------------------------------------------------ 各位,若对以上100题任何一道,或对已上传的任何一题的答案, 有任何问题,请把你的思路、想法,回复到此帖子上, 微软等100题系列,永久维护地址(2010年11.26日): http://topic.csdn.net/u/20101126/10/b4f12a00-6280-492f-b785-cb6835a63dc9.html
此为我个人搜集整理的, 精选微软等公司,有关 数据结构和算法的面试100题[前40题], 此绝对值得你下载收藏。 网友yui评论,真是够多的了,从此,不用再看其它面试题.... 一句话,请享用。 其它资源,下载地址: 1.[最新答案V0.3版]微软等数据结构+算法面试100题[第21-40题答案] http://download.csdn.net/source/2832862 2.[第1题-60题汇总]微软等数据结构+算法面试100题 http://download.csdn.net/source/2826690 3.[答案V0.2版]精选微软数据结构+算法面试100题[前20题]--修正 http://download.csdn.net/source/2813890 //此份答案是针对最初的V0.1版本,进行的校正与修正。 4.[答案V0.1版]精选微软数据结构+算法面试100题[前25题] http://download.csdn.net/source/2796735 5.[第二部分]精选微软等公司结构+算法面试100题[前41-60题]: http://download.csdn.net/source/2811703 6.[第一部分]精选微软等公司数据结构+算法经典面试100题[1-40题] http://download.csdn.net/source/2778852 更多资源,下载地址: http://v_july_v.download.csdn.net/ //请继续期待,后续内容。 ------------------------------------------------------ 各位,若对以上100题任何一道,或对已上传的任何一题的答案, 有任何问题,请把你的思路、想法,回复到此帖子上, 微软等100题系列,永久维护地址(2010年11.26日): http://topic.csdn.net/u/20101126/10/b4f12a00-6280-492f-b785-cb6835a63dc9.html -------July、2010年12月2日。
资源说明: 此份,是为微软等公司数据结构+算法面试100 题,之前60 题的汇总。 总结整理了前第1 题-第60 题。特此并作此一份上传。以飨各位。:)。 此绝对值得你下载收藏。 ----------------------------- 网友yui评论,真是够多的了,从此,不用再看其它面试题.... 一句话,请享用。 July、2010/11.12. ------------------------------------------------ 其它资源,下载地址: [最新整理公布][汇总II]微软等数据结构+算法面试100题[第1-80题] http://download.csdn.net/source/2846055 1.[最新答案V0.3版]微软等数据结构+算法面试100题[第21-40题答案] http://download.csdn.net/source/2832862 2.[第1题-60题汇总]微软等数据结构+算法面试100题 http://download.csdn.net/source/2826690 3.[答案V0.2版]精选微软数据结构+算法面试100题[前20题]--修正 http://download.csdn.net/source/2813890 //此份答案是针对最初的V0.1版本,进行的校正与修正。 4.[答案V0.1版]精选微软数据结构+算法面试100题[前25题] http://download.csdn.net/source/2796735 5.[第二部分]精选微软等公司结构+算法面试100题[前41-60题]: http://download.csdn.net/source/2811703 6.[第一部分]精选微软等公司数据结构+算法经典面试100题[1-40题] http://download.csdn.net/source/2778852 更多资源,下载地址: http://v_july_v.download.csdn.net/ ------------------------------------------------------ 各位,若对以上100题任何一道,或对已上传的任何一题的答案, 有任何问题,请把你的思路、想法,回复到此帖子上, 微软等100题系列,永久维护地址(2010年11.26日): http://topic.csdn.net/u/20101126/10/b4f12a00-6280-492f-b785-cb6835a63dc9.html
精选微软等数据结构+算法面试100题答案修正V0.2版本 -------------------- 此份答案是针对,前期已公布的最初的那份答案的,初步校正与修正。 http://download.csdn.net/source/2796735(V0.1版) 相比第一份V0.1版答案,此份答案V0.2版更加准确,亦修正了不少题目的答案。 此份20题的答案,思路更加清晰易懂,简介明了。 请享用。July、2010/11/06。 其它资源,下载地址: 1.[最新答案V0.3版]微软等数据结构+算法面试100题[第21-40题答案] http://download.csdn.net/source/2832862 2.[第1题-60题汇总]微软等数据结构+算法面试100题 http://download.csdn.net/source/2826690 3.[答案V0.2版]精选微软数据结构+算法面试100题[前20题]--修正 http://download.csdn.net/source/2813890 //此份答案是针对最初的V0.1版本,进行的校正与修正。 4.[答案V0.1版]精选微软数据结构+算法面试100题[前25题] http://download.csdn.net/source/2796735 5.[第二部分]精选微软等公司结构+算法面试100题[前41-60题]: http://download.csdn.net/source/2811703 6.[第一部分]精选微软等公司数据结构+算法经典面试100题[1-40题] http://download.csdn.net/source/2778852 更多资源,下载地址: http://v_july_v.download.csdn.net/ ------------------------------------------------------ 各位,若对以上100题任何一道,或对已上传的任何一题的答案, 有任何问题,请把你的思路、想法,回复到此帖子上, 微软等100题系列,永久维护地址(2010年11.26日): http://topic.csdn.net/u/20101126/10/b4f12a00-6280-492f-b785-cb6835a63dc9.html

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧