刚看到个贴子,说有网友同事跳槽成功,工资直接涨了8000。结果第一天入职,老板一句话就把气氛拉满:挖你的人把你夸上天了,你得对得起这个价。

我觉得这事吧,其实一点不稀奇。涨薪从来不是白给的,市场给你抬价,公司就会顺手把期待也抬上去。就像你买贵点的水果,回家一切发现不甜,心里肯定不爽,老板心态也差不多。
网友们的回复我看了看,有人说这是PUA,有人劝赶紧跑。我倒觉得没那么极端。这话确实有压力,但更多是提前把话摊开:高工资=高要求。怕的不是老板说这句话,而是你心里没数,还指望混日子。
从我的角度看,跳槽涨薪这事,别光盯着数字。钱多了,活、标准、盯你的眼睛也都会多。扛得住,是机会;扛不住,再高的工资也只是暂住。
很多人一说“算法题”就头大,其实放到生活里就好理解了。 就拿“2016 年的投资”来说吧,这种题本质上就是:钱放哪儿、放多久,最后最多能变成多少。
我们自己把题意梳理一下,假设是这么一个场景(方便你记住思路,也方便你自己改数据):
从 2016 年开始,你有一笔钱
P,准备连续投资N年。 银行有 3 种定期产品:
1 年期,年利率 r12 年期,年利率 r23 年期,年利率 r3每次产品到期以后,你可以立刻把所有钱再投任意一种新的产品。 问:N 年之后,你手里的钱最多能变成多少?
输入可以是:P, N, r1, r2, r3,输出就是一个最大金额。
其实这就是个典型的动态规划模型:时间轴 + 决策。
粗暴一点的想法是:我每一年去枚举,我今年投 1 年期还是 2 年期还是 3 年期,结果就是组合爆炸,分分钟 2 的 N 次方,跑不动。
这种“从现在往后随便选”的,特别适合改成“从过去往现在推”:
0 是 2016 年初,1 是 2017 年初…)dp[i] 表示:从 2016 年出发,到了第 i 年手里最多能有多少金额那到了第 i 年这笔钱是怎么来的呢?只有几种可能:
dp[i] 至少可以等于 dp[i-1]dp[i-1] * (1 + r1)dp[i-2] * (1 + r2)dp[i-3] * (1 + r3)于是状态转移就很自然了:
dp[i] = max( dp[i], // 不投/活期,钱保持不变 dp[i-1] * (1 + r1), // 之前投了 1 年期 dp[i-2] * (1 + r2), // 之前投了 2 年期 dp[i-3] * (1 + r3) // 之前投了 3 年期)注意边界:只有当 i - term >= 0 的时候,这个选择才合法。
初始化也很简单:
dp[0] = P,表示 2016 年初刚拿到本金dp[i] = dp[i-1] 或者直接 0,在转移里不断取 max 就行整体复杂度就是 O(N * K),K 是产品种类数,这里是 3,等于 O(N),线性时间,很稳。
下面给一份比较完整、但不复杂的 Java 写法,你可以按自己实际题目的输入输出改一改:
import java.util.Scanner;publicclassInvest2016{/** * 计算从 2016 年开始投资 years 年后的最大资产 * * @param principal 初始本金 * @param years 投资年数 * @param rates 各种期限的利率,rates[0] 是 1 年期,rates[1] 是 2 年期,rates[2] 是 3 年期 * @return 最大金额 */publicstaticdoublemaxInvest(double principal, int years, double[] rates){double[] dp = newdouble[years + 1]; dp[0] = principal;for (int i = 1; i <= years; i++) {// 至少可以啥也不干,钱保持不变(相当于活期) dp[i] = dp[i - 1];// 尝试 1 年期、2 年期、3 年期for (int term = 1; term <= 3; term++) {int prevYear = i - term;if (prevYear >= 0) {double candidate = dp[prevYear] * (1 + rates[term - 1]);if (candidate > dp[i]) { dp[i] = candidate; } } } }return dp[years]; }publicstaticvoidmain(String[] args){ Scanner sc = new Scanner(System.in);// 示例输入:本金 年数 r1 r2 r3// 比如:10000 5 0.035 0.04 0.045double principal = sc.nextDouble();int years = sc.nextInt();double r1 = sc.nextDouble();double r2 = sc.nextDouble();double r3 = sc.nextDouble(); sc.close();double[] rates = {r1, r2, r3};double result = maxInvest(principal, years, rates);// 输出保留两位小数 System.out.printf("%.2f%n", result); }}可以自己随便带几个小样例玩一玩,比如:
你就会发现: 有时候“干脆一开始就上 3 年期”,不一定比“先买个 1 年期看看,再滚到 2 年期”差或者好,这就是为什么要用 DP,而不是凭感觉选。
题目名字叫“2016 年的投资”,但本质就是一个时间维度的动态规划,你以后看到“从起点滚到终点、每一步可以做不同选择”的场景,都可以想到这种写法。
如果你那道题的题面跟我假设的不太一样,比如产品更多、收益率每年变,甚至有手续费之类的,都可以在这个 DP 框架上稍微改一改就行。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html