百度春招笔试 系统研发工程师 题解
第一题,经典题,给一个长度为n的数字,往里面插入k个乘号,求最大可能的乘积。我用了记忆化搜索。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> using namespace std; unsigned long long dp[100][100]; int n, k; int val[100]; string input; unsigned long long getval(int lend, int rend); unsigned long long dfs(int nn, int kk) { if(kk == 0) return (dp[nn][kk] = getval(0, nn)); if(kk < 0) return 0; if(dp[nn][kk] != -1) return dp[nn][kk]; if(kk > nn) return (dp[nn][kk] = 0); unsigned long long ans = 0, temp; for(int i = 0; i < nn; i++)//The pre multiply sign is after i-th number { temp = dfs(i, kk - 1) * getval(i + 1, nn); ans = max(ans, temp); } return (dp[nn][kk] = ans); } unsigned long long getval(int lend, int rend)//zuobi youbi { unsigned long long ans = 0; for(int i = lend; i <= rend; i++) { ans = ans * 10; ans += val[i]; } return ans; } int main(void) { memset(dp, -1, sizeof(dp)); cin >> n >> k; cin >> input; for(int i = 0; i < n; i++) val[i] = input[i] - '0'; cout << dfs(n - 1, k) << endl; return 0; }
有一些小的bug,做了大概30min。
第二题,每个节点出度只有1,求整个图最小的环的大小。因为我没有保存代码所以说一下思路。
思路就是dfs,用一个dis数组记录距离,初始化为-1;如果搜索到一个已经搜过的节点(dis[i] != -1),那么说明有环,直接减一下就可以。
这道题的麻烦之处在于可能有多个连通块,如果我们只从1号节点开始dfs,只能通过30%的数据。
那么如何处理多个连通块呢?这里一不小心,可能会只通过0%的数据,如果你这么写的话:
for(int i = 1;i <= n;i++) if(dis[i] == -1) dfs(i);
为什么呢?想象这样的情况:
1 ->2; 2 ->3; 3 ->2
如果我们之前已经搜索了2,3;这次从1开始搜索,那么2 3 这个环的大小就会被错误计算。
我的解决方案是使用并查集,每个连通块只dfs一次。我们能够保证如果每个连通块有环,那么dfs一次一定能找到对应的环。
代码因为忘了保存,希望楼下有聚聚能够贴上来qaq
#春招#