程序员老鬼

从大厂辞职,上岸事业编的6个月,我emo了。收入砍了一半,生活的扣扣嗖嗖,原来上岸只是一座围城,我站在城里不知所措

刚看到个贴子,说有网友从大厂辞职上岸事业编,六个月就emo了。收入砍半,日子过得紧巴巴,感叹“原来上岸只是座围城”。这话太真实了。

Image

不是编制不好,而是每个人想要的生活不同。大厂拼的是钱和机会,体力换自由;体制内拼的是稳定和节奏,时间换安全感。问题是,很多人上岸前以为进了天堂,结果发现是个慢节奏的牢笼。

网友们的回复我也看了,有的劝她“知足常乐”,有的说“劝人上岸,天打雷劈”。其实都没错,只是位置不同。你拿高薪就得受折磨,拿稳定就得忍枯燥,鱼和熊掌确实不能兼得。

换个角度想,上岸不是终点,是另一种生活方式的开始。别纠结失去了什么,先看看自己真正需要什么。【备注:文末可领最新资料】

算法题:倒水

两个水壶,容量分别是 x 和 y,要量出恰好 t 升水。操作就那几样:装满、倒空、互相倒,直到其中一个壶里出现 t。约束别忘了,t ≤ max(x,y),而且 t 必须是 gcd(x,y) 的倍数,不然干啥都白搭。

这玩意最稳的是把每个“状态”当图里的点,状态=(A壶当前量,B壶当前量)。从(0,0)出发,用 BFS 一层层扩散。六种操作产生邻居:装满A、装满B、倒空A、倒空B、A→B、B→A。第一次遇到“某壶==t”就是最短步数,还能顺带回溯打印步骤。为啥是最短?因为 BFS 天然按步数层层推进。

Java 代码

import java.util.*;

publicclassWaterJugBFS{
staticclassNode{
int a, b;           // 当前两壶水量
        Node prev;          // 上一步
        String op;          // 到达本步的操作描述
        Node(int a, int b, Node prev, String op) {
this.a = a; this.b = b; this.prev = prev; this.op = op;
        }
    }

publicstatic List<String> solve(int X, int Y, int T){
if (T == 0) return List.of("啥也不干:已得到 0");
if (T > Math.max(X, Y) || T % gcd(X, Y) != 0) return List.of("无解");

boolean[][] vis = newboolean[X + 1][Y + 1];
        Queue<Node> q = new ArrayDeque<>();
        Node start = new Node(0, 0, null, "开始 (0,0)");
        q.add(start); vis[0][0] = true;

while (!q.isEmpty()) {
            Node cur = q.poll();
if (cur.a == T || cur.b == T) return buildPath(cur);

for (Node nxt : expand(cur, X, Y)) {
if (!vis[nxt.a][nxt.b]) {
                    vis[nxt.a][nxt.b] = true;
                    q.add(nxt);
                }
            }
        }
return List.of("无解");
    }

static List<Node> expand(Node n, int X, int Y){
        List<Node> list = new ArrayList<>(6);
// 1) 装满A
        list.add(new Node(X, n.b, n, "装满A -> (" + X + "," + n.b + ")"));
// 2) 装满B
        list.add(new Node(n.a, Y, n, "装满B -> (" + n.a + "," + Y + ")"));
// 3) 倒空A
        list.add(new Node(0, n.b, n, "倒空A -> (0," + n.b + ")"));
// 4) 倒空B
        list.add(new Node(n.a, 0, n, "倒空B -> (" + n.a + ",0)"));
// 5) A -> B
int moveAB = Math.min(n.a, Y - n.b);
        list.add(new Node(n.a - moveAB, n.b + moveAB, n,
"A->B " + moveAB + " -> (" + (n.a - moveAB) + "," + (n.b + moveAB) + ")"));
// 6) B -> A
int moveBA = Math.min(n.b, X - n.a);
        list.add(new Node(n.a + moveBA, n.b - moveBA, n,
"B->A " + moveBA + " -> (" + (n.a + moveBA) + "," + (n.b - moveBA) + ")"));
return list;
    }

static List<String> buildPath(Node end){
        LinkedList<String> steps = new LinkedList<>();
        Node p = end;
while (p != null) {
            steps.addFirst(p.op);
            p = p.prev;
        }
        steps.add("完成:已有 " + end.a + " 或 " + end.b + " 等于目标");
return steps;
    }

staticintgcd(int a, int b){ return b == 0 ? a : gcd(b, a % b); }

// 小样例
publicstaticvoidmain(String[] args){
int X = 3, Y = 5, T = 4;
        List<String> ans = solve(X, Y, T);
        ans.forEach(System.out::println);
    }
}

复杂度

BFS 最多遍历 (X+1)*(Y+1) 个状态,所以时间、空间都在 O(XY) 量级。坑点两个:一是先做可行性剪枝(t 超界或不整除 gcd),省掉无谓搜索;二是倒水时别忘了“倒到对方满了或自己空了为止”的两重限制,用 min(当前, 对方剩余) 一把梭。

就这样,思路清、代码短、还能把完整操作步骤打出来。你把 X、Y、T 换成面试官给的就行,过。

-END-

我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

最后给大家分享一份不错的副业资料,点击下方公众号,回复关键字: 副业 领取,也可以链接我领取,微信:hls404