【美團點評】2020校招算法工程師方向筆試題


這套題難啊。。好多坑點。而且想了好久。交卷兩小時。。想了一晚上。

第一題還是不知道怎么dp的。。可能要坑一下明天補。。

如果有大佬能指點下我就更好了QAQ。我是真的菜。。

我來補題了哈哈哈哈哈哈哈哈哈!!終於過了

 


 

 

試題鏈接:2020校招算法工程師方向筆試題

 

5、 外賣小哥的保溫箱

題意:眾所周知,美團外賣的口號是:”美團外賣,送啥都快”。身着黃色工作服的騎手作為外賣業務中商家和客戶的重要紐帶,在工作中,以快速送餐突出業務能力;工作之余,他們會通過玩智力游戲消遣閑暇時光,以反應速度彰顯智慧,每位騎手拿出裝有貨物的保溫箱,參賽選手需在最短的時間內用最少的保溫箱將貨物裝好。

 

我們把問題簡單描述一下:

 

1 每個貨物占用空間都一模一樣

 

2 外賣小哥保溫箱的最大容量是不一樣的,每個保溫箱由兩個值描述: 保溫箱的最大容量 bi ,當前已有貨物個數 ai ,(ai<=bi)

 

3 貨物轉移的時候,不必一次性全部轉移,每轉移一件貨物需要花費 1秒 的時間

 

 

題解:我這個題用貪心只過了30%。。而且我花了一晚上時間想怎么dp。。想不出來。

討論區大佬說貪心只能得到最優k。QAQ我先坑一下。。明天補吧可能

終於AC了。感謝gg傾情指導。雖然還是找了半下午的bug//

 

這個題是一個背包dp。嗯,我背包dp學的可差了。

我們用dp[i]來表示當前容量為i時所需要的最少背包數。(貨物為goods[],容量為cap[])

外層需要遍歷所有的背包容量,內層來做這個dp處理。(外層這里用i,內層用j來表示)

此時的狀態轉移方程也就是dp[j] = min(dp[j],dp[j-cap[i]]+1),

這里就需要注意到j-cap[i]因為j是從sum_cap遍歷到1的。防止負數情況出現,做一個負數為0的處理。

然后我們這里只是做了使用最少背包數的dp處理。但是並不知道time。time是由貨物的轉移來決定的。所以我們用一個額外的數組weight[]來表示貨物多的。因為轉移貨物越多,花時間越長,所以保存貨物多的情況。

那我們此時會出現三種情況。

1、dp[j] < dp[j-cap[i]]+1  當前背包大於,那么直接不處理。因為我們要保證背包最小

2、dp[j] > dp[j-cap[i]]+1  比當前背包要小,那么更新背包,並且將貨物加上。

3、dp[j] = dp[j-cap[i]]+1  相同的情況,保證留下的貨物是最大的。

背包這個過程進行完以后,進行一個遍歷,找最優的k,以及最優k對應留下的背包里的貨物總量。

那么我們所需要的時間t = sum_goods-max_weight啦!!!

分析就是上面這些,代碼可能會更清晰。

 

代碼:

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1e5+10;
 4 int n;
 5 
 6 int goods[maxn];
 7 int cap[maxn];
 8 int dp[maxn]; 
 9 int weight[maxn];
10 
11 int main(){
12     cin>>n;
13     int sum_goods = 0;
14     int sum_cap = 0;
15     for(int i = 0;i < n; i++){
16         cin>>goods[i];
17         sum_goods += goods[i];
18     }
19     for(int i = 0;i < n ; i++){
20         cin>>cap[i];
21         sum_cap += cap[i];
22     }
23 
24     memset(dp,0x3f,sizeof(dp));
25     memset(weight,0,sizeof(weight));
26 
27     dp[0] = 0;
28     weight[0] = 0;
29     for(int i = 0; i < n ;i++){
30         //遍歷容量dp[j]:容量為j時需要的最少背包數
31         for(int j = sum_cap; j > 0 ; j--){
32             int res = max(j-cap[i],0);
33             //大於直接下一個
34             if(dp[j] < dp[res]+1)   continue;
35             //小於,更新一下背包數。並且把貨物容量更新
36             else if(dp[j] > dp[res]+1){
37                 dp[j] = dp[res]+1;
38                 weight[j] = weight[res]+goods[i];
39             }
40             //相等的時候取貨物大的情況
41             else{
42                 weight[j] = max(weight[j],weight[res]+goods[i]);
43             }
44         }
45     }
46 
47     int k = 0x3f;
48     int max_weight = 0;
49 
50     for(int i = sum_goods; i <= sum_cap; i++){
51         if(dp[i] < k){
52             k = dp[i];
53             max_weight = weight[i];
54         }
55         else if(dp[i] == k){
56             max_weight = max(max_weight,weight[i]);
57         }
58     }
59 
60     cout<<k<<" "<<sum_goods-max_weight<<endl;
61 
62 
63     return 0;
64 }
View Code

 

 

  

6、字符串最長公共前綴

題意:輸入n個字符串(1<=n<=3*102,字符串總長度不超過103,只包含小寫字母)

 

后面多次查詢,每次查詢輸入兩個數字x,y,輸出第x個字符串和第y個字符串的最長公共前綴長度。(查詢次數不超過102)

 

 

題解:字符串丟進vector.然后輸入要比較的兩個字符串的索引。(記得有多組數據)

循環在第二個字符串找第一個字符串的當前字符,然后不停截取就可以了。最后輸入前綴的長度即可。

 

代碼:

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 vector<string> v;
 5 
 6 int main(){
 7     int n;
 8     cin>>n;
 9     string str;
10     for( int i = 0 ;i < n ;i++){
11         cin>>str;
12         v.push_back(str);
13     }
14     int a,b;
15     while(cin>>a>>b){
16         a--;b--;
17         string ans = v[a];
18         while(v[b].find(ans)){
19             ans = ans.substr(0,ans.size()-1);
20         }
21 
22         int cnt = ans.size();
23         cout<<cnt<<endl;
24     }
25 
26     return 0;
27 }
View Code

 

 

 

7、字符串排序

題意:生活中經常有需要將多個字符串進行排序的需要,比如將美團點評的部分業務名稱(外賣、打車、旅游、麗人、美食、結婚、旅游景點、教培、門票、酒店),用拼音表示之后按字母逆序排序。字母逆序指從z到a排序,比如對兩個字符串排序時,先比較第一個字母按字母逆序排z在a的前面,當第一個字母一樣時再比較第二個字母按字母逆序排,以此類推。特殊情況1)空字符串需排在最前面;2)若一個短字符串是另一個長字符串的前綴則短字符串排在前面。請自行實現代碼進行排序,直接調用sort等排序方法將不得分且視為作弊。

 

題解:這個主要是理解題意。。我剛開始沒看題用sort過了30%?,手寫了一個快排。

然后沒注意里面那個前綴的判斷,過了40%。。也就是我們需要重寫一個比較。你用函數也可以,重載運算符也可以。

根據它兩個條件來就行了。因為是用的升序排列,最后輸出要逆序。

再提一點:字符串輸入的處理,我是用判斷到','把字符串存儲丟進vector.然后再清空字符串繼續操作。

 

代碼:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1010;
 4 
 5 vector<string> v;
 6 
 7 bool cmp(string a,string b){
 8     if(a == "")   return true;
 9     if(b.find(a) == 0 && a != b)    return true;
10     if(a.find(b) == 0 && a != b)    return false;
11     if(a > b)   return true;
12 
13     return false;
14 }
15 
16 void qsort(int left,int right){
17     string res = v[left];
18     if(left >= right)  return;
19     int l = left;
20     int r = right;
21     while(l != r){
22         while(l < r && cmp(res,v[r]) == false){
23             r--;
24         }
25         swap(v[l],v[r]);
26 
27         while(l< r && cmp(res,v[l])){
28             l++;
29         }
30         swap(v[l],v[r]);
31     }
32 
33     qsort(left,l-1);
34     qsort(l+1,right);
35 }
36 
37 int main(){
38     string s;
39     cin>>s;
40     int len = s.size();
41 
42     int index = 0;
43     string str;
44     v.clear();
45     while(index <= len){
46         if(s[index] == ',' || index == len){
47             v.push_back(str);
48             str.clear();
49             index++;
50         }
51         else{
52             str += s[index];
53             index++;
54         }
55     }
56 
57     
58     qsort(0,v.size()-1);
59     for(int i = v.size()-1;i >0 ;i--){
60         cout<<v[i]<<",";
61     }
62     
63 
64     cout<<v[0]<<endl;
65 
66     return 0;
67 }
View Code

 

 

 

8、 工作安排

題意:小美是團隊的負責人,需要為團隊制定工作的計划,以幫助團隊產出最大的價值。

每周團隊都會有兩項候選的任務,其中一項為簡單任務,一項為復雜任務,兩項任務都能在一周內完成。第i周,團隊完成簡單任務的價值為li,完成復雜任務的價值為hi。由於復雜任務本身的技術難度較高,團隊如果在第i周選擇執行復雜任務的話,需要在i-1周不做任何任務專心准備。如果團隊在第i周選擇執行簡單任務的話,不需要提前做任何准備。

現在小美的團隊收到了未來N周的候選任務列表,請幫助小美確定每周的工作安排使得團隊的工作價值最大。

 

題解:哎,上去貪心也是30%。后面發現不是。。是個比較簡單的dp。

思考一下兩個狀態。我們需要用兩周的時間做判斷。

1、做兩周的簡單工作。  easy[i-1] + easy[i]

2、准備一周,做一周的難工作。  diff[i]

這一周的狀態是由前兩周來決定,。

所以可以得到狀態轉移方程dp[i] = max(dp[i-1] + easy[i],dp[i-2] + diff[i])

初始化的時候記得dp[0]和dp[1]都要初始化掉,

 

代碼:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1010;
 4 
 5 int easy[maxn];
 6 int diff[maxn];
 7 int dp[maxn];
 8 
 9 int main(){
10     int n;
11     cin>>n;
12     for(int i = 0 ;i < n ;i++){
13         cin>>easy[i]>>diff[i];
14     }
15     dp[0] = max(easy[0],diff[0]);
16     dp[1] = max(dp[0]+easy[1],diff[1]);
17 
18     for(int i = 2;i <= n; i++){
19         dp[i] = max(dp[i-1]+easy[i],dp[i-2]+diff[i]);
20     }
21     cout<<dp[n-1]<<endl;
22 
23     return 0;
24 }
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM