面试算法题

有a,b,c,d四个人,现在有三个酒杯X,Y,Z三个不规则酒杯, X,Y容量为8两,现在已装满酒,Z容量为3两,为空杯.现在要求四个人每人都能平均喝到4两酒,请说出该怎么喝?写出算法,并打印出每步X,Y,Z杯内的酒多少和四个人每人所喝的酒?


import java.util.HashSet;
import java.util.Stack;

public class Drink {
// state 为32位整数,每4bit表示一个cup
// cup 0-2 : cup x,y,z
// cup 3-6 : people a,b,c,d
// state := [D][C][B][A][Z][Y][X]

int[] maxVol = {8, 8, 3, 4, 4, 4, 4}; // 最大容量
int stopState = makeState(new int[]{0, 0, 0, 4, 4, 4, 4}); // 最终状态

Stack<Integer> stateStack = new Stack<Integer>();
HashSet<Integer> stateStackCache = new HashSet<Integer>();
HashSet<Integer> failStates = new HashSet<Integer>();

public static void main(String[] args) {
new Drink().start();
}

static int getCup(int state, int i) {
return (state & (0xF << (i * 4))) >> (i * 4);
}

static int makeState(int curState, int cupIdx, int value) {
return value << (4 * cupIdx) | (curState & (~(0xF << (4 * cupIdx))));
}

static int makeState(int curState, int cupIdx1, int value1, int cupIdx2, int value2)

{
return makeState(makeState(curState, cupIdx1, value1), cupIdx2, value2);
}

// cup.length MUST == 7
static int makeState(int[] cup) {
int state = 0;
for (int i = 6; i >= 0; i--) {
state |= cup[i];
if (i > 0)
state <<= 4;
}
return state;
}


void start() {
boolean r = testState(makeState(new int[]{8, 8, 0, 0, 0, 0, 0}));
System.out.println(r ? "found" : "not found");
}

boolean testState(int curState) {
if (stateStackCache.contains(curState) || failStates.contains(curState))
return false;

pushState(curState);
try {
if (curState == stopState) {
printStack();
return true;
}

if (testMoves(curState)) {
return true;
} else {
failStates.add(curState);
return false;
}
} finally {
popState(curState);
}
}

private boolean testMoves(int curState) {
for (int from = 0; from < 3; from++) {
int curCupFrom = getCup(curState, from);
if (curCupFrom == 0)
continue;

for (int to = 6; to >= 0; to--) {
if (to == from)
continue;

int curCupTo = getCup(curState, to);
int maxTo = maxVol[to] - curCupTo;
if (maxTo == 0)
continue;

int moveValue = curCupFrom;
if (curCupFrom > maxTo) {
if (to >= 3) //people
continue;
moveValue = maxTo;
}

int newCupFrom = curCupFrom - moveValue;
int newCupTo = curCupTo + moveValue;

if (from < 2 && to < 2 && newCupTo == curCupFrom) {
//两个同样的杯子倒来倒去
continue;
}

final int newState = makeState(curState, from, newCupFrom, to,

newCupTo);

if (testState(newState))
return true;
}
}
return false;
}

private void printStack() {
System.out.println("Success! all steps: " + stateStack.size());
int step = 0;
for (Integer state : stateStack) {
System.out.print("\t" + (++step) + ":\t");
for (int i = 0; i < 7; i++) {
System.out.print(getCup(state, i));
if (i == 2)
System.out.print(" | ");
}
System.out.println();
}
}

private void popState(int newState) {
stateStack.pop();
stateStackCache.remove(newState);
}

private void pushState(int newState) {
stateStack.push(newState);
stateStackCache.add(newState);
}
}


不是偶写的,能写出来这个算法的人是个牛人
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值