1. 程式人生 > >網易2017春招實習生筆試程式設計題集合(C++方向)

網易2017春招實習生筆試程式設計題集合(C++方向)

挺早之前做好一直想寫一篇部落格分享一下,但是後來給忘了…C++方向一共十二道程式設計題,可能和別的方向有一些出入。題目總體的難度不大,有些題有些小坑,適合進階者練練手,本文比較長,建議直接進github看程式碼,如有錯誤歡迎指出,也歡迎大家討論!

程式碼都扔在Github了 -> Github

題目列表:

① 調整佇列

② 分餅乾

③ 雙核處理

④ 堆磚塊

⑤ 奇怪的表示式求值

⑥ 小易記單詞

⑦ 工作安排

⑧ 凃棋盤

⑨ 消除重複元素

⑩ 趕去公司

⑪ 集合

⑫ 魔力手環

[Problem 1]:調整佇列

在幼兒園有n個小朋友排列為一個隊伍,從左到右一個挨著一個編號為(0~n - 1)。其中有一些是男生,有一些是女生,男生用’B’表示,女生用’G’表示。小朋友們都很頑皮,當一個男生挨著的是女生的時候就會發生矛盾。作為幼兒園的老師,你需要讓男生挨著女生或者女生挨著男生的情況最少。你只能在原隊形上進行調整,每次調整隻能讓相鄰的兩個小朋友交換位置,現在需要儘快完成隊伍調整,你需要計算出最少需要調整多少次可以讓上述情況最少。例如:GGBBG->GGBGB->GGGBB
這樣就使之前的兩處男女相鄰變為一處相鄰,需要調整隊形2次
輸入描述 :
輸入資料包括一個長度為n且只包含G和B的字串.n不超過50.
輸出描述 :
輸出一個整數,表示最少需要的調整隊伍的次數
輸入例子 :
GGBBG
輸出例子 :
2

這題只分兩種情況,男女相挨著的情況最少,那麼就是G都在左邊或者B都在左邊,兩種情況模擬一下然後min就是答案了。
實現程式碼:

#include<iostream>
//#include<map>
#include<algorithm>
#include<string>
#include<vector>
//#include<numeric>
//#include<cmath>
//#include<set>

using namespace std;

string QUEUE;
int result, Num_G = 0
, Num_B = 0; vector<int>Result_G, Result_B; int main() { cin >> QUEUE; size_t len = QUEUE.size(); int i = 0; int sum_G = 0, sum_B = 0; //auto it = QUEUE.begin(), END = QUEUE.end(); while (i < len) { if (QUEUE[i] == 'G') { ++Num_G; Result_G.push_back(i); } if (QUEUE[i] == 'B') { ++Num_B; Result_B.push_back(i); } ++i; } for (i = 0; i < Num_G; ++i)sum_G += (Result_G[i] - i); for (i = 0; i < Num_B; ++i)sum_B += (Result_B[i] - i); result = min(sum_B, sum_G); cout << result << endl; return 0; }

[Problem 2]:分餅乾

易老師購買了一盒餅乾,盒子中一共有k塊餅乾,但是數字k有些數位變得模糊了,看不清楚數字具體是多少了。易老師需要你幫忙把這k塊餅乾平分給n個小朋友,易老師保證這盒餅乾能平分給n個小朋友。現在你需要計算出k有多少種可能的數值
輸入描述 :
輸入包括兩行:
第一行為盒子上的數值k,模糊的數位用X表示,長度小於18(可能有多個模糊的數位)
第二行為小朋友的人數n
輸出描述 :
輸出k可能的數值種數,保證至少為1
輸入例子 :
9999999999999X
3
輸出例子 :
4

最笨也是最直接的方法當然是X用0~9然後挨個試一遍,牛客討論區看到有人這樣能AC,但是我死活過不了不知道為什麼…然後用了另一種方法,是從討論區看到的思路,1個數在除以一個數的過程中,是從前往後一位一位除的,能否除的盡,要看前面的餘數和當前的數的組合能否除的盡,所以要記錄前面一位所有的餘數可能性。比如 :

X2
2

X除2的餘數可能是0 ,1,是0的可能性為X=0,2,4,6,8 五種,取1的可能性為X=1,3,5,7,9 也是五種,這個時候再看個位數的2,2和前面的餘數0/1的組合為02/12,也就是說到了這一位餘數為0的可能性為上一位餘數為0/1兩種情況總數的和,因為02,12餘2都是0,k=5+5=10種。
感覺有點類似於推公式,找規律,不那麼容易想到。
也看到有另一種思路的,將k分拆為多個數,比如123X45,那麼可能總數就是123000+X45(X列舉0~9),若(123000%n+X45%n)=n的倍數,則此種情況成立,最後算一個總和,大家可以嘗試一下。
實現程式碼:

#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<ctype.h>
#include<sstream>
//#include<numeric>
//#include<cmath>
//#include<set>

using namespace std;

long long sync[10001], remain[10001];   //每一位數對應餘數取值的可能性
int main() {
    string s;
    int n;
    cin >> s;
    cin >> n;
    sync[0] = 1;
    int s_size = s.size();
    for (int i = 0; i < s_size; ++i) {
        memset(remain, 0, sizeof(remain));
        for (int j = 0; j < n; j++) {       //這一位所能取的餘數的可能性(0...n-1)
            for (int k = 0; k < 10; k++) {    //這一位能取的數,當然是0~9啦
                if (isdigit(s[i]) && s[i] - '0' != k) continue;
                //isdigit 判斷是否為0~9的數字
                //若該位為k,則計算所有可能取值,否則只計算這一種取值
                remain[((j * 10) + k) % n] += sync[j];
                //計算當前值和前一位餘數的取值組合產生的餘數
            }
        }
        memcpy(sync, remain, sizeof(sync));  //與餘數對應的取值同步
    }
    cout << sync[0] << endl;  //最後一位餘數為0的的取值
}

[Problem 3]:雙核處理

一種雙核CPU的兩個核能夠同時的處理任務,現在有n個已知資料量的任務需要交給CPU處理,假設已知CPU的每個核1秒可以處理1kb,每個核同時只能處理一項任務。n個任務可以按照任意順序放入CPU進行處理,現在需要設計一個方案讓CPU處理完這批任務所需的時間最少,求這個最小的時間。
輸入描述 :
輸入包括兩行:
第一行為整數n(1 ≤ n ≤ 50)
第二行為n個整數length[i](1024 ≤ length[i] ≤ 4194304),表示每個任務的長度為length[i]kb,每個數均為1024的倍數。
輸出描述 :
輸出一個整數,表示最少需要處理的時間
輸入例子 :
5
3072 3072 7168 3072 1024
輸出例子 :
9216

其實這是一道簡單的動態規劃題,雙核處理,我們只要處理其中的一半,然後和剩下的一半對比時間哪個更少就行了,把它轉化為經典的0-1揹包模型,其實就是代價所獲價值都是length[i],思路在註釋裡了,solve部分優化了空間,優化的部分建議大家參考hihocoder-1038這道題,過程寫得可以說是非常詳細了1038# 0-1揹包
實現程式碼:

#include<iostream>
//#include<map>
#include<algorithm>
//#include<string>
#include<vector>
#include<numeric>
//#include<cmath>
//#include<set>
using namespace std;
const int MAX_SIZE = 51;
vector<int> Length_n;

int n;

//使得max(cpu_one_time,cpu_two_time)最小
//   =====> 01 bag 模型:
//體積為sum/2,共有n個物體,代價為t[i],價值也是t[i],儘量多的裝
//0-1 bag 思路補充:
//有N件物品和一個容量為V的揹包。第i件物品的費用是c[i],價值是w[i],求解將哪些物品放入揹包可使價值總和最大
//特點: 每一件物品僅有一件,能夠選擇放或者不放。 
//定義狀態:F[i][v]:表示前i件物品恰好放入一個容量為v的揹包能夠獲得的最大的價值 
//轉移方程:F[i][v]=max(F[i-1][v],F[i-1][v-c[i]]+w[i]]); 
//優化空間複雜度: 以上求法時間和空間複雜度均為O(V*N),時間複雜度不能在優化了,然而空間複雜度能夠進一步優化
//我們這樣考慮:僅僅用一個數組F[0..V],保證第i次迴圈結束結束後F[v]表示的是就是定義的狀態F[i][v]


int solve(vector<int>& Len, int sum) {
    int halfsum = sum >> 1;
    vector<int> DP(halfsum + 1, 0);
    for (int i = 0; i < n; ++i) {
        for (int j = halfsum; j >= Len[i]; --j)
            DP[j] = max(DP[j], DP[j - Len[i]] + Len[i]);
    }
    return DP[halfsum];
}

int main() {
    cin >> n; int item;
    for (int i = 0; i < n; ++i) {
        cin >> item;
        Length_n.push_back(item / 1024);
    }
    //sort(Length_n.begin(), Length_n.end());
    int SUM = accumulate(Length_n.begin(), Length_n.end(), 0);
    int result = max(solve(Length_n, SUM), SUM - solve(Length_n, SUM));
    cout << result * 1024 << endl;
    return 0;
}

[Problem 4]:堆磚塊

小易有n塊磚塊,每一塊磚塊有一個高度。小易希望利用這些磚塊堆砌兩座相同高度的塔。
為了讓問題簡單,磚塊堆砌就是簡單的高度相加,某一塊磚只能使用在一座塔中一次。
小易現在讓能夠堆砌出來的兩座塔的高度儘量高,小易能否完成呢。
輸入描述:
輸入包括兩行:
第一行為整數n(1 ≤ n ≤ 50),即一共有n塊磚塊
第二行為n個整數,表示每一塊磚塊的高度height[i] (1 ≤ height[i] ≤ 500000)
輸出描述:
如果小易能堆砌出兩座高度相同的塔,輸出最高能拼湊的高度,如果不能則輸出-1.
保證答案不大於500000。
輸入例子:
3
2 3 5
輸出例子:
5

唉這題不多說了!也是動態規劃!剛入門的時候動態規劃是真的磨人,然後帶著nowcoder上的示例程式碼求教了我們學校ACM的人才懂了解題思路… (╯︵╰)
從沒有磚塊開始分析。
考慮每塊磚塊放入的決策,放入左邊,放入右邊和不使用這塊磚塊三種情況,dp[p][gap]表示只用前p塊磚堆成高度相差gap的兩座塔的較高的一座的塔的高度,所以gap + height[i]當作往左邊塔放入磚塊,gap - height當作右邊塔放入磚塊 右邊塔放入時高度也會增加,如果不放入就用前置狀態,三個求最大值,因為只需要知道[P-1][]就可以求出[P][]所以把p迴圈置0置1(滾動陣列)節省空間。
實現程式碼:


#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>

using namespace std;
const int MAX_NUM = 500010;
int n;
int DP[2][MAX_NUM];

int solve(vector<int>& len) {
    memset(DP, 0, sizeof(DP));  //initialize the DP array
    int p = 0;
    auto len_size = len.size();
    for (int i = 0; i < len_size; ++i) {
        DP[p][len[i]] = max(DP[1 - p][len[i]], len[i]);
        for (int gap = 0; gap < MAX_NUM; ++gap) {
            if (DP[1 - p][gap]) {  //if the tower exsists
                if (DP[p][gap] < DP[1 - p][gap])DP[p][gap] = DP[1 - p][gap];
                DP[p][gap + len[i]] = max(DP[p][gap + len[i]], max(DP[1 - p][gap + len[i]], DP[1 - p][gap] + len[i]));
                DP[p][abs(gap - len[i])] = max(DP[p][abs(gap - len[i])], max(DP[1 - p][abs(gap - len[i])], max(DP[1 - p][gap] - gap + len[i], DP[1 - p][gap])));
            }
        }
        p = 1 - p;
    }
    int result = (DP[1 - p][0]) ? DP[1 - p][0] : -1;
    return result;
}

int main() {
    vector<int> length;
    cin >> n;
    int item;
    for (int i = 0; i < n; ++i) {
        cin >> item; length.push_back(item);
    }
    int result = solve(length);
    cout << result << endl;
    return 0;
}

/*
//簡書上看到了另一個版本的,解法大同小異,這裡也放上來對比
//但是感覺這一種解法的可讀性更好


#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
int dp[2][2*N]; //第一維滾動狀態 第二維兩個塔的差值
int height[55];
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
scanf("%d", &height[i]);
}
memset(dp, 0, sizeof(dp));
int p = 0;

for (int j = 0; j < 2*N; j++) dp[1-p][j] = INT_MIN; //保證第一次取不到
dp[1-p][N] = 0;//入口
for (int i = 1; i <= n; i++)
{
for (int j = height[i]; j < 2*N; j++)
{
dp[p][j] = max(dp[1-p][j-height[i]]+height[i], dp[1-p][j]); //放到右邊減小差距並增加塔高 以及不放入磚塊
}
for (int j = 0; j+height[i] < 2*N; j++)
{
dp[p][j] = max(dp[p][j], dp[1-p][j+height[i]]); //放到左邊增加差距
}
p = 1 - p;
}
if (dp[1-p][N]) cout << dp[1-p][N] << endl;
else cout <<-1;
return 0;
}
*/

[Problem 5]:奇怪的表示式求值

常規的表示式求值,我們都會根據計算的優先順序來計算。比如, / 的優先順序就高於 + -。但是小易所生活的世界的表示式規則很簡單,從左往右依次計算即可,而且小易所在的世界沒有除法,意味著表示式中沒有 / ,只有(+, -和 )。現在給出一個表示式,需要你幫忙計算出小易所在的世界這個表示式的值為多少
輸入描述 :
輸入為一行字串,即一個表示式。其中運算子只有 - , +, *。參與計算的數字只有0~9.
保證表示式都是合法的,排列規則如樣例所示。
輸出描述 :
輸出一個數,即表示式的值
輸入例子 :
3 + 5 * 7
輸出例子 :
56

這題算是簽到題了,據我所知很多人筆試的時候死在考慮了括號(),實際輸入沒有括號,所以只要不斷地往右讀取運算子計算結果讀取計算讀取計算就可以了,不多說。
實現程式碼:

#include<iostream>
//#include<map>
#include<algorithm>
#include<string>
//#include<vector>
//#include<cmath>
//#include<set>

using namespace std;

int main() {

    string expression;
    int result;
    cin >> expression;
    auto it = expression.begin();
    result = *(it++) - '0';
    while (it != expression.end()) {
        if (*it == '+') {
            result = result + (*(++it) - '0');
            ++it; continue;
        }
        else if (*it == '*') {
            result = result *(*(++it) - '0');
            ++it; continue;
        }
        else if (*it == '-') {
            result = result - (*(++it) - '0');
            ++it; continue;
        }
    }
    cout << result << endl;
    return 0;
}

[Problem 6]:小易記單詞

小易參與了一個記單詞的小遊戲。遊戲開始系統提供了m個不同的單詞,小易記憶一段時間之後需要在紙上寫出他記住的單詞。小易一共寫出了n個他能記住的單詞,如果小易寫出的單詞是在系統提供的,將獲得這個單詞長度的平方的分數。
注意小易寫出的單詞可能重複,但是對於每個正確的單詞只能計分一次。
輸入描述 :
輸入資料包括三行:
第一行為兩個整數n(1 ≤ n ≤ 50)和m(1 ≤ m ≤ 50)。以空格分隔
第二行為n個字串,表示小易能記住的單詞,以空格分隔,每個單詞的長度小於等於50。
第三行為m個字串,系統提供的單詞,以空格分隔,每個單詞的長度小於等於50。
輸出描述 :
輸出一個整數表示小易能獲得的分數
輸入例子 :
3 4
apple orange strawberry
strawberry orange grapefruit watermelon
輸出例子 :
136

這也算一道簽到題吧。能記住的單詞中,重複的不計分,那麼把單詞存到一個set裡,剩下的給出的單詞約束好了不會重複,那麼存在一個vector裡面就好了,然後不斷查詢,如果出現就計分,最終輸出一下和。
實現程式碼:

#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
//#include<numeric>
//#include<cmath>
#include<set>
using namespace std;
//const int MAX_SIZE = 51;
int n, m;
vector<string> Sys;
set<string> Rem;

int solve(set<string>& rem, vector<string>& sys) {
    int result = 0;
    auto flag = sys.end();
    auto sbegin = rem.begin(), send = rem.end();
    for (; sbegin != send; ++sbegin) {
        if (find(sys.begin(), sys.end(), *sbegin) != flag)result += ((*sbegin).size()*(*sbegin).size());
    }
    return result;
}
int main() {
    cin >> n >> m;
    int result;
    string item;
    for (int i = 0; i < n; ++i) {
        cin >> item;
        Rem.insert(item);
    }
    for (int i = 0; i < m; ++i) {
        cin >> item;
        Sys.push_back(item);
    }
    result = solve(Rem, Sys);
    cout << result << endl;
    return 0;
}

[Problem 7]:工作安排

現在有n位工程師和6項工作(編號為0至5),現在給出每個人能夠勝任的工作序號表(用一個字串表示,
比如:045,表示某位工程師能夠勝任0號,4號,5號工作)。現在需要進行工作安排,
每位工程師只能被安排到自己能夠勝任的工作當中去,兩位工程師不能安排到同一項工作當中去。
如果兩種工作安排中有一個人被安排在的工作序號不一樣就被視為不同的工作安排,現在需要計算出有多少種不同工作安排計劃。
輸入描述:
輸入資料有n+1行:
第一行為工程師人數n(1 ≤ n ≤ 6)
接下來的n行,每行一個字串表示第i(1 ≤ i ≤ n)個人能夠勝任的工作(字串不一定等長的)
輸出描述:
輸出一個整數,表示有多少種不同的工作安排方案
輸入例子:
6
012345
012345
012345
012345
012345
012345
輸出例子:
720

這道題目的資料量不大,所以可以直接用暴力列舉過,如果資料量再大一點大概就要動態規劃來優化了…我們用一個arranged陣列來記錄工作是否已經被安排,workable陣列記錄每個工程師能夠勝任的工作,然後列舉所有情況。主要還是資料量不多,所以還是比較好過的啦。
實現程式碼:


//資料量不大,直接用DFS暴力列舉
//資料大了就GG了...

#include<iostream>
#include<cstring>
#include<string>
using namespace std;
bool workable[6][6];
bool arranged[6];           //記錄工作是否已被安排,避免繼續遞迴時重複訪問.
int n;
int dfs(int now) {
    int ans = 0;
    for (int i = 0; i < 6; i++) {
        if (workable[now][i] && !arranged[i]) {
            arranged[i] = true;
            if (now == 0)
                ++ans;
            else
                ans += dfs(now - 1);
            arranged[i] = false;
        }
    }
    return ans;
}
int main() {
    cin >> n;
    memset(workable, 0, sizeof(workable));
    memset(arranged, 0, sizeof(arranged));
    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        int s_size = s.size();
        for (int j = 0; j < s_size; ++j)
            workable[i][s[j] - '0'] = true;
    }
    cout << dfs(n - 1) << endl;
    return 0;
}

[Problem 8]:凃棋盤

小易有一塊n*n的棋盤,棋盤的每一個格子都為黑色或者白色,小易現在要用他喜歡的紅色去塗畫棋盤。
小易會找出棋盤中某一列中擁有相同顏色的最大的區域去塗畫,幫助小易算算他會塗畫多少個棋格。
輸入描述 :
輸入資料包括n + 1行:
第一行為一個整數n(1 ≤ n ≤ 50), 即棋盤的大小
接下來的n行每行一個字串表示第i行棋盤的顏色,’W’表示白色,’B’表示黑色
輸出描述 :
輸出小易會塗畫的區域大小
輸入例子 :
3
BWW
BBB
BWB
輸出例子 :
3

擁有相同顏色的最大區域,那麼這塊區域必須是連續的,我用了兩個不同的flag計數,結果儲存在對應的count陣列中,所以在連續計數的過程中,如果出現了別的顏色,那麼就要立刻把計數flag清零,然後不斷更新最大值,最後sort一下,返回兩者的最大值。
實現程式碼:


#include<iostream>
//#include<map>
#include<algorithm>
#include<string>
#include<vector>
#include<numeric>
//#include<cmath>
//#include<set>
using namespace std;
const int MAX_SIZE = 51;

vector<string> ChessBoard(MAX_SIZE);
int n, paint_num;
int solve(vector<string>& CB) {
    vector<int> count_w(MAX_SIZE, 1), count_b(MAX_SIZE, 1);
    int flag_w, flag_b;
    for (int i = 0; i < n; ++i) {   //i是列
        flag_b = flag_w = 0;
        for (int j = 0; j < n; ++j) {    //j是行
            if (CB[j][i] == 'W') {
                ++flag_w; flag_b = 0;
                if (flag_w > count_w[j])count_w[j] = flag_w;
            }
            else if (CB[j][i] == 'B') {
                ++flag_b; flag_w = 0;
                if (flag_b > count_b[j])count_b[j] = flag_b;
            }
        }
    }
    sort(count_w.rbegin(), count_w.rend());
    sort(count_b.rbegin(), count_b.rend());
    return max(count_w[0], count_b[0]);
}
int main() {
    cin >> n;
    for (int i = 0; i < n; ++i)cin >> ChessBoard[i];
    int result = solve(ChessBoard);
    cout << result << endl;
    return 0;
}

[Problem 9]:消除重複元素

小易有一個長度為n序列,小易想移除掉裡面的重複元素,但是小易想是對於每種元素保留最後出現的那個。小易遇到了困難, 希望你來幫助他。
輸入描述 :
輸入包括兩行:
第一行為序列長度n(1 ≤ n ≤ 50)
第二行為n個數sequence[i](1 ≤ sequence[i] ≤ 1000),以空格分隔
輸出描述 :
輸出消除重複元素之後的序列,以空格分隔,行末無空格
輸入例子 :
9
100 100 100 99 99 99 100 100 100
輸出例子 :
99 100

也是一道簽到題。。。map儲存每個數對應出現的次數,然後遞減,最後一次出現的元素push_back到數組裡,然後把陣列順序輸出就好了
實現程式碼:

#include<iostream>
#include<map>
//#include<algorithm>
//#include<string>
#include<vector>
#define MAXSIZE 51
using namespace std;

int a[MAXSIZE];
map<int, int>COUNT; //標記元素出現的次數
vector<int>FINAL;   //儲存最終的不重複序列

int main() {
    int n; cin >> n;
    for (int i = 0; i < n; ++i)cin >> a[i];
    for (int i = 0; i < n; ++i)++COUNT[a[i]]; //開始計數
    for (int i = 0; i < n; ++i) {             //將最後一個不重複元素push_back
        --COUNT[a[i]];
        if (!COUNT[a[i]]) {
            FINAL.push_back(a[i]);
        }
    }
    size_t sz = FINAL.size();
    for (int i = 0; i < sz; ++i) {          //輸出容器中的不重複元素,注意格式
        if (i == sz - 1)cout << FINAL[i];
        else cout << FINAL[i] << ' ';
    }
    cout << endl;
    return 0;
}

[Problem 10]:趕去公司

終於到週末啦!小易走在市區的街道上準備找朋友聚會,突然伺服器發來警報, 小易需要立即回公司修復這個緊急bug。假設市區是一個無限大的區域,每條街道假設座標是(X,Y),小易當前在(0,0)街道,辦公室在(gx, gy)街道上。小易周圍有多個計程車打車點,小易趕去辦公室有兩種選擇,一種就是走路去公司,另外一種就是走到一個計程車打車點,然後從打車點的位置坐計程車去公司。每次移動到相鄰的街道(橫向或者縱向)走路將會花費walkTime時間,打車將花費taxiTime時間。小易需要儘快趕到公司去,現在小易想知道他最快需要花費多少時間去公司。
輸入描述 :
輸入資料包括五行:
第一行為周圍計程車打車點的個數n(1 ≤ n ≤ 50)
第二行為每個計程車打車點的橫座標tX[i](-10000 ≤ tX[i] ≤ 10000)
第三行為每個計程車打車點的縱座標tY[i](-10000 ≤ tY[i] ≤ 10000)
第四行為辦公室座標gx, gy(-10000 ≤ gx, gy ≤ 10000), 以空格分隔
第五行為走路時間walkTime(1 ≤ walkTime ≤ 1000)和taxiTime(1 ≤ taxiTime ≤ 1000), 以空格分隔
輸出描述 :
輸出一個整數表示,小易最快能趕到辦公室的時間
輸入例子 :
2
- 2 - 2
0 - 2
- 4 - 2
15 3
輸出例子 :
42

整個區域就是一個直角座標系,先把走路到達的時間算好。然後每次計算走路去打車點+打車到辦公室兩段路程的時間和,求出最小的時間就是了,應該也是一道簽到題………
實現程式碼:

#include<iostream>
#include<map>
#include<cmath>
#include<algorithm>
//#include<string>
#include<vector>
#define MAXSIZE 51
using namespace std;

#define LOOP(n) for(int i=0;i<n;++i)

struct TaxiLoc
{
    int Tx;
    int Ty;
};
int n, Gx, Gy;
int walktime, taxitime;

int main() {
    TaxiLoc TL[MAXSIZE];
    cin >> n;
    LOOP(n)cin >> TL[i].Tx;
    LOOP(n)cin >> TL[i].Ty;
    cin >> Gx >> Gy;
    cin >> walktime >> taxitime;
    int answer = walktime*(abs(Gx) + abs(Gy));
    LOOP(n) {
        int pivot = taxitime*(abs(Gx - TL[i].Tx) + abs(Gy - TL[i].Ty)) + walktime*(abs(TL[i].Tx) + abs(TL[i].Ty));
        answer = min(pivot, answer);
    }
    cout << answer << endl;
    return 0;
}

[Problem 11]:集合

小易最近在數學課上學習到了集合的概念, 集合有三個特徵:1.確定性 2.互異性 3.無序性.小易的老師給了小易這樣一個集合:
S = { p / q | w ≤ p ≤ x, y ≤ q ≤ z }
需要根據給定的w,x,y,z, 求出集合中一共有多少個元素。小易才學習了集合還解決不了這個複雜的問題, 需要你來幫助他。
輸入描述 :
輸入包括一行:
一共4個整數分別是w(1 ≤ w ≤ x),x(1 ≤ x ≤ 100),y(1 ≤ y ≤ z),z(1 ≤ z ≤ 100).以空格分隔
輸出描述 :
輸出集合中元素的個數
輸入例子 :
1 10 1 1
輸出例子 :
10

理解題意:這個集合裡面存的是p/q,並且是需要經過分數約分的,那麼我們設立pair對映p/q,再把這個pair存在set當中,就行了,重點在分數的約分
實現程式碼:

#include<set>
using namespace std;

set<pair<int, int>> SET;
int w, x, y, z;
int gcd(int x, int y) //用輾轉相除法,求兩數的最大公約數
{
    int r;
    while (y > 0)
    {
        r = x%y;
        x = y;
        y = r;
    }
    return x;
}

int main() {
    cin >> w >> x >> y >> z;
    for (int i = w; i <= x; ++i)
        for (int j = y; j <= z; ++j) {
            int p = i, q = j;
            int div = gcd(i, j);
            SET.insert(make_pair(i / div, j / div));
        }
    int set_size = SET.size();
    cout << set_size << endl;
    return 0;
}

[Problem 12]:魔力手環

小易擁有一個擁有魔力的手環上面有n個數字(構成一個環), 當這個魔力手環每次使用魔力的時候就會發生一種奇特的變化:每個數字會變成自己跟後面一個數字的和(最後一個數字的後面一個數字是第一個), 一旦某個位置的數字大於等於100就馬上對100取模(比如某個位置變為103, 就會自動變為3).現在給出這個魔力手環的構成,請你計算出使用k次魔力之後魔力手環的狀態。
輸入描述 :
輸入資料包括兩行:
第一行為兩個整數n(2 ≤ n ≤ 50)和k(1 ≤ k ≤ 2000000000), 以空格分隔
第二行為魔力手環初始的n個數,以空格分隔。範圍都在0至99.
輸出描述 :
輸出魔力手環使用k次之後的狀態,以空格分隔,行末無空格。
輸入例子 :
3 2
1 2 3
輸出例子 :
8 9 7

剛開始看題!以為這是個簽到題,按題意模擬了一下,怎麼都過不了,只能過一部分資料,看了樣例發現數據量特別大就TLE了。這裡需要使用矩陣快速冪來優化時間複雜度。把魔力環看成是一個一維向量,最終的結果相當於魔力環構成的一維向量[0…n-1]與
[1 1 0 0 …]
[0 1 1 0 …]
[0 0 1 1 …]
[………..]
[1 0 0…..1]
這樣的矩陣相乘,矩陣的快速冪我也是參考了別人的blog,矩陣快速冪參考
然後還是看程式碼吧:

#include<iostream>
    //#include<map>
#include<algorithm>
    //#include<string>
#include<vector>
    //#include<numeric>
    //#include<cmath>
    //#include<set>
const int MAX_SIZE = 101;
using namespace std;
typedef vector<vector<int>> Matrix;

const int MOD = 100;
vector<int> Magic;
int n; long long int k;

Matrix Matrix_init(MAX_SIZE, vector<int>(MAX_SIZE, 0));
void Make_init(Matrix& Matrix_init) {
    for (int i = 0; i < n; ++i) {
        Matrix_init[i][i] = Matrix_init[i][(i + 1) % n] = 1;
    }
}
/*
k的數量級太大,直接甩你一個TLE
void Solve(vector<int>& Magic) {
int flag = Magic[0];
for (long long int i = 0; i < k; ++i) {
for (int j = 0; j < n; ++j) {
if (j == n - 1)Magic[j] += flag;
else Magic[j] += Magic[j + 1];
if (Magic[j] > 100)Magic[j] %= 100;
}
flag = Magic[0];
}
}
*/
//
//最終的結果相當於 魔力環構成的一維向量[0...n-1]與
//  [1 1 0 0 ...]
//  [0 1 1 0 ...]
//  [0 0 1 1 ...]
//  [...........]
//  [1 0 0.....1]
//  這樣的矩陣相乘
//  為了在規定時間內執行,利用矩陣的快速冪優化  
//快速冪blog參考:http ://blog.csdn.net/hikean/article/details/9749391

Matrix Matrix_mul(Matrix a, Matrix b) {
    Matrix temp(n, vector<int>(n, 0));
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j) {
            for (int k = 0; k < n; ++k) {
                temp[i][j] += a[i][k] * b[k][j];
                temp[i][j] %= MOD;
            }

        }
    return temp;
}

Matrix Quick_pow(Matrix a, long long int k) {
    long long int N = k;
    Matrix ANS(n, vector<int>(n, 0));
    for (int i = 0; i < n; ++i)
        ANS[i][i] = 1;
    while (N) {
        if (N & 1) {  //即n%2
            ANS = Matrix_mul(ANS, a);
        }
        N = N >> 1;   //即n=n/2
        a = Matrix_mul(a, a);
    }
    return ANS;
}

vector<int> Magic_mul(vector<int> Magic, Matrix BASE) {
    vector<int> temp;
    int flag;
    for (int i = 0; i < n; ++i) {
        flag = 0;
        for (int k = 0; k < n; ++k) {
            flag = (flag + Magic[k] * BASE[i][k]) % MOD;
        }
        temp.push_back(flag);
    }
    return temp;
}

int main() {
    cin >> n;
    cin >> k;
    int item;
    for (int i = 0; i < n; ++i) {
        cin >> item;
        Magic.push_back(item);
    }
    Matrix BASE(n, vector<int>(n, 0));
    Make_init(Matrix_init);
    BASE = Quick_pow(Matrix_init, k);
    Magic = Magic_mul(Magic, BASE);
    for (int i = 0; i < n; ++i) {
        (i == n - 1) ? cout << Magic[i] : cout << Magic[i] << ' ';
    }
    cout << endl;
    return 0;
}

總結一下:這次春招實習筆試的難度其實不大,很多資料的坑都在題目裡面幫你限制好了,變相的降低了題目的難度。但是筆試的時候加上前面的選擇主觀,能拿滿分的也是很優秀了吧,公眾號的推文裡面看到C++方向的全卷滿分有6個,膜膜膜,希望大家在秋招和來年的春招都能有好offer拿啦。

相關推薦

2017實習生筆試程式設計集合C++方向

挺早之前做好一直想寫一篇部落格分享一下,但是後來給忘了…C++方向一共十二道程式設計題,可能和別的方向有一些出入。題目總體的難度不大,有些題有些小坑,適合進階者練練手,本文比較長,建議直接進github看程式碼,如有錯誤歡迎指出,也歡迎大家討論! 程式

2017筆試程式設計集合題解

前言 想想已經有一年多沒有接觸演算法題了,忙活了一年多沒什麼用的東西,才陡然發現自己竟然就要畢業了,然而審視了下自己的水平估計還達不到大一的程度,甚是驚恐。於是下定決心開始刷一點題,打好基本功。正好有同學在做網易筆試題的時候來向我問問題,我看了看有12道,好像也不多,於是就順便刷了刷。本

2017筆試編程集合——分餅幹

out color div nbsp -1 pre new har nco 參考:http://blog.csdn.net/wwe4023/article/details/70171648的內容 // import java.util.*; public class M

2017筆試編程集合10——小易記單詞

bsp math 字符串 array 如果 new 是否 數據 作用 小易參與了一個記單詞的小遊戲。遊戲開始系統提供了m個不同的單詞,小易記憶一段時間之後需要在紙上寫出他記住的單詞。小易一共寫出了n個他能記住的單詞,如果小易寫出的單詞是在系統提供的,將獲得這個單詞長度的平方

2017筆試編程集合8——奇怪的表達式求值

next ann new switch 運算 ase 自己 lin pri 常規的表達式求值,我們都會根據計算的優先級來計算。比如*/的優先級就高於+-。但是小易所生活的世界的表達式規則很簡單,從左往右依次計算即可,而且小易所在的世界沒有除法,意味著表達式中沒有/,只有(+

2017筆試編程集合7——集合

復雜 bsp span 問題 args 一個 add port code 小易最近在數學課上學習到了集合的概念,集合有三個特征:1.確定性 2.互異性 3.無序性.小易的老師給了小易這樣一個集合:S = { p/q | w ≤ p ≤ x, y ≤ q ≤ z }需要根據給

2017筆試——集合

集合 題目 小易最近在數學課上學習到了集合的概念,集合有三個特徵:1.確定性 2.互異性 3.無序性. 小易的老師給了小易這樣一個集合: S = { p/q | w ≤ p ≤ x

2017筆試Java程式碼

一種雙核CPU的兩個核能夠同時的處理任務,現在有n個已知資料量的任務需要交給CPU處理,假設已知CPU的每個核1秒可以處理1kb,每個核同時只能處理一項任務。n個任務可以按照任意順序放入CPU進行處理,現在需要設計一個方案讓CPU處理完這批任務所需的時間最少

2017筆試編程集合題解

平分 數組 如果 方案 順序 clu 不同 std 編程題 1、雙核處理 題目 一種雙核CPU的兩個核能夠同時的處理任務,現在有n個已知數據量的任務需要交給CPU處理,假設已知CPU的每個核1秒可以處理1kb,每個核同時只能處理一項任務。n個任務可以按照任意順序放入CPU進

2017[編程]分餅幹@Java

lower ipa ndt uic following store pro space mfc o6b19TK菜3孤Whttp://www.docin.com/app/user/userinfo?userid=178838282 eO白懊窒1癱9肯3鈉E山段http://

2017.04.18:2017資料分析開放

1.異常值檢測 原因: (1)資料來源於不同的類:某個資料物件可能不同於其他資料物件(即異常),因為它術語一個不同的型別或類。Hawkins的離群點定義:離群點是一個觀測值,它與其他觀測值的差別如此之大,以至於懷疑它是由不同的機制產生的。 (2)自然變異:許多資料集可以用一

2018筆試程式設計——nk數對

題目描述:牛牛以前在老師那裡得到了一個正整數數對(x, y), 牛牛忘記他們具體是多少了。 但是牛牛記得老師告訴過他x和y均不大於n, 並且x除以y的餘數大於等於k。 牛牛希望你能幫他計算一共有多少個可能的數對。首先用兩個for迴圈來暴力求解是可以得到結果,但是時

【線上筆試題解題報告系列】2017內推筆試程式設計【持續更新】

網易今年把內推筆試放在牛客網上辦,然後出了一批程式設計題。 題目在: 一共18個,好多(不同崗位抽3個不同的題的樣子)…… 慢慢寫吧,做一題寫一題。 以下題解將假定讀者有下列知識,對下面所列舉的細節不再贅述。 (如果有必要對此進行教學的,請站內信我) C/C++的基本

2018筆試

前不久被網易的筆試虐了2次,因此特地做一個記錄:給出2個數a, b(b必定是偶數), 把a變成b,其中有3種操作:+2, 需要對應的cost,-2,  需要對應的cost*2,  需要對應的cost,求a變成b需要的最少cost當時腦子一熱,就用bfs, 用一個結構體儲存狀態

機器學習筆試題目----2016

2016年3月23日參加了網易機器學習崗的筆試,然後又被鄙視了。因為不允許截圖和拍照,只憑記憶記錄了一些問題。 1、常見的生成式模型和判別式模型有哪些? 生成式模型:HMM、樸素貝葉斯 判別式模型:svm、最大熵模型、決策樹、神經網路、條件隨機場。 2、

2018年計算機視覺實習生筆試程式設計

牛牛總是睡過頭,所以他定了很多鬧鐘,只有在鬧鐘響的時候他才會醒過來並且決定起不起床。從他起床算起他需要X分鐘到達教室,上課時間為當天的A時B分,請問他最晚可以什麼時間起床輸入描述:每個輸入包含一個測試用例。 每個測試用例的第一行包含一個正整數,表示鬧鐘的數量N(N<=1

2017程式設計:暗黑的字串 [python]

''' [程式設計題] 暗黑的字串 時間限制:1秒 空間限制:32768K 一個只包含'A'、'B'和'C'的字串,如果存在某一段長度為3的連續子串中恰好'A'、'B'和'C'各有一個, 那麼這個字串就是純淨的,否則這個字串就是暗黑的。例如: BAACAACCBAAA 連續

2017程式設計集合

You are always too soft. 1、如果一個數字序列逆置之後跟原序列是一樣的就稱這樣的數字序列為迴文序列。例如:{1, 2, 1}, {15, 78, 78, 15} , {112} 是迴文序列, {1, 2, 2}, {15, 78, 87, 51} ,

2018實習生筆試程式設計

平面內有n個矩形, 第i個矩形的左下角座標為(x1[i], y1[i]), 右上角座標為(x2[i], y2[i])。 如果兩個或者多個矩形有公共區域則認為它們是相互重疊的(不考慮邊界和角落)。 請你計算出平面內重疊矩形數量最多的地方,有多少個矩形相互重疊。 輸入描述:輸入包括五行。 第一行包括一個整數n(2

2017程式設計:迴文序列 [python]

''' [程式設計題] 迴文序列 時間限制:1秒 空間限制:32768K 如果一個數字序列逆置之後跟原序列是一樣的就稱這樣的數字序列為迴文序列。例如: {1, 2, 1}, {15, 78, 78, 15} , {112} 是迴文序列,  {1, 2, 2}, {15, 7