【網易】2018校招筆試題


一丶魔法幣 

小易准備去魔法王國采購魔法神器,購買魔法神器需要使用魔法幣,但是小易現在一枚魔法幣都沒有,但是小易有兩台魔法機器可以通過投入x(x可以為0)個魔法幣產生更多的魔法幣。
魔法機器1:如果投入x個魔法幣,魔法機器會將其變為2x+1個魔法幣
魔法機器2:如果投入x個魔法幣,魔法機器會將其變為2x+2個魔法幣
小易采購魔法神器總共需要n個魔法幣,所以小易只能通過兩台魔法機器產生恰好n個魔法幣,小易需要你幫他設計一個投入方案使他最后恰好擁有n個魔法幣。

思路:一開始DFS搜索 即使最深30層 也只拿了60分 

     操作一,一定使當前數變成奇數

   操作二,一定使當前數變成偶數 

每次對當前數進行判斷 是由哪一步變來的 倒退回去即可

 1 #include <cstdio>
 2 #include <cctype>
 3 
 4 const int MAXN=1000010;
 5 
 6 int n,tot;
 7 
 8 int a[MAXN];
 9 
10 bool flag;
11 
12 bool DFS(int x) {
13     if(x>n) return false;
14     if(x==n) return true;
15     if(DFS(2*x+1)) {a[++tot]=1;return true;}
16     if(DFS(2*x+2)) {a[++tot]=2;return true;}
17     return false;
18 }
19 
20 int hh() {
21     scanf("%d",&n); 
22      DFS(0);
23     for(int i=tot;i;--i) printf("%d",a[i]);
24     return 0;
25 }
26 
27 int sb=hh();
28 int main(int argc,char**argv) {;}
DFS
 1 #include <cstdio>
 2 #include <cctype>
 3 
 4 const int MAXN=100;
 5 
 6 int n,tot;
 7 
 8 int a[MAXN];
 9 
10 bool flag;
11 
12 int hh() {
13     scanf("%d",&n); 
14     while(n) {
15         if(n%2==0) {
16             a[++tot]=2;
17             n=(n-2)/2;
18         }
19         else {
20             a[++tot]=1;
21             n=(n-1)/2;
22         }
23     }
24     for(int i=tot;i;--i) printf("%d",a[i]);
25     return 0;
26 }
27 
28 int sb=hh();
29 int main(int argc,char**argv) {;}
正解

二丶相反數

為了得到一個數的"相反數",我們將這個數的數字順序顛倒,然后再加上原先的數得到"相反數"。例如,為了得到1325的"相反數",首先我們將該數的數字順序顛倒,我們得到5231,之后再加上原先的數,我們得到5231+1325=6556.如果顛倒之后的數字有前綴零,前綴零將會被忽略。例如n = 100, 顛倒之后是1.

思路:倒過來與原數加一遍即可

 1 #include <cstdio>
 2 #include <cctype>
 3 
 4 int n,t,len;
 5 
 6 int a[10];
 7 
 8 int hh() {
 9     scanf("%d",&n);
10     int k=n;
11     while(k) {
12         a[++len]=k%10;
13         k/=10;
14     }
15     int l=1;
16     for(int i=len;i;--i) t+=l*a[i],l*=10;
17     printf("%d\n",t+n);
18     return 0;
19 }
20 
21 int sb=hh();
22 int main(int argc,char**argv) {;}
代碼

三丶字符串碎片

一個由小寫字母組成的字符串可以看成一些同一字母的最大碎片組成的。例如,"aaabbaaac"是由下面碎片組成的:'aaa','bb','c'。牛牛現在給定一個字符串,請你幫助計算這個字符串的所有碎片的平均長度是多少。

思路:ans=字符串長度/字符串碎片的個數 

     一個字符串碎片一定是由同一種字母組成 不需要考慮太多

 1 #include <cstdio>
 2 #include <cctype>
 3 #include <cstring>
 4 
 5 const int MAXN=1010;
 6 
 7 int len,sum;
 8 
 9 char s[MAXN];
10 
11 int hh() {
12     scanf("%s",s+1);
13     len=strlen(s+1);
14     for(int i=1;i<=len;++i) if(s[i]!=s[i-1]) ++sum;
15     double ans=(double)len/sum;
16     printf("%.2lf",ans);
17     return 0;
18 }
19 
20 int sb=hh();
21 int main(int argc,char**argv) {;}
代碼

四丶游歷魔法王國

魔法王國一共有n個城市,編號為0~n-1號,n個城市之間的道路連接起來恰好構成一棵樹。
小易現在在0號城市,每次行動小易會從當前所在的城市走到與其相鄰的一個城市,小易最多能行動L次。
如果小易到達過某個城市就視為小易游歷過這個城市了,小易現在要制定好的旅游計划使他能游歷最多的城市,請你幫他計算一下他最多能游歷過多少個城市(注意0號城市已經游歷了,游歷過的城市不重復計算)。

思路:分兩種情況討論 

    一是當小易走的步數小於樹的最長鏈 

    二是當小易走的步數大於最長鏈 

      這時候 最長鏈是一定要走的 那剩下的步數最優的情況是走一步走過的城市 再到一個沒走過的城市 再退回來 再走沒走的城市

      這樣最多可以走(L-MAX_L)/2個城市 

    最后min(n,MAX_L+(L-MAX_L)/2) 

DFS好像有60分

 1 #include <cstdio>
 2 #include <cctype>
 3 #include <vector>
 4 
 5 const int MAXN=110;
 6 
 7 int n,l,ans;
 8 
 9 bool vis[MAXN];
10 
11 std::vector<int> Graph[MAXN];
12 
13 void DFS(int u,int step,int mx) {
14     if(step==l) {
15         ans=mx>ans?mx:ans;
16         return;
17     }
18     for(int i=0;i<Graph[u].size();++i) {
19         int v=Graph[u][i];
20         if(!vis[v]) vis[v]=true,DFS(v,step+1,mx+1),vis[v]=false;
21         else DFS(v,step+1,mx);
22     }
23 }
24 
25 int hh() {
26     scanf("%d%d",&n,&l);
27     for(int x,i=1;i<n;++i) {
28         scanf("%d",&x);
29         ++x;
30         Graph[x].push_back(i+1);
31         Graph[i+1].push_back(x);
32     }
33     vis[1]=true;
34     DFS(1,0,0);
35     printf("%d\n",ans+1);
36     return 0;
37 }
38 
39 int sb=hh();
40 int main(int argc,char**argv) {;}
DFS
 1 #include <cstdio>
 2 #include <cctype>
 3 #include <vector>
 4 #define min(a,b) a>b?b:a
 5 
 6 const int MAXN=110;
 7 
 8 int n,l,ans;
 9 
10 int dp[MAXN],p[MAXN];
11 
12 int hh() {
13     scanf("%d%d",&n,&l);
14     for(int i=0;i<n-1;++i) scanf("%d",&p[i]);
15     
16     int mx=-1;
17     for(int i=0;i<n-1;++i) {
18         dp[i+1]=dp[p[i]]+1;
19         ans=ans>dp[i+1]?ans:dp[i+1];
20     }
21     ans=min(ans,l);
22     printf("%d\n",min(n,1+ans+(l-ans)/2)); 
23     
24     return 0;
25 }
26 
27 int sb=hh();
28 int main(int argc,char**argv) {;}
貪心

五丶重排數列

小易有一個長度為N的正整數數列A = {A[1], A[2], A[3]..., A[N]}。
牛博士給小易出了一個難題:
對數列A進行重新排列,使數列A滿足所有的A[i] * A[i + 1](1 ≤ i ≤ N - 1)都是4的倍數。
小易現在需要判斷一個數列是否可以重排之后滿足牛博士的要求。

思路:我們用 1 表示 這個數是4的倍數

       0 表示 這個數不是4的倍數

     顯然 一個合法的序列有 1 0 1 0 1 0... 或者 0 1 0 1 0 1 0....

    當然 兩個 同為 2的倍數 的數也可以被4整除 所以 0 1 0 1 2 2 2 2.... 這樣的也是合法序列

所以統計一個數列中 4的倍數 2的倍數 和其他數的個數 

不存在2的倍數時 4的倍數的個數 和不是4的倍數的個數只差1個數 

存在2的倍數 則要求 4的倍數的個數要大於等於不是4的倍數的個數 否則  0 1 0 2 2 2.... 這樣的序列是不合法的

 

 1 #include <cstdio>
 2 #include <cctype>
 3 
 4 const int MAXN=100010;
 5 
 6 int T,n,A,B,C;
 7 
 8 int a[MAXN];
 9 
10 inline void read(int&x) {
11     int f=1;register char c=getchar();
12     for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar());
13     for(;isdigit(c);x=x*10+c-48,c=getchar());
14     x=x*f;
15 }
16 
17 int hh() {
18     read(T);
19     while(T--) {
20         read(n);
21         A=B=C=0;
22         for(int i=1;i<=n;++i) {
23             read(a[i]);
24             if(a[i]%4==0) ++A;
25             else if(a[i]%2==0) ++B;
26             else ++C; 
27         }
28         int t=n/2;
29         if(t==A||n-t==A) printf("Yes\n");
30         else {
31             if(A>=C) printf("Yes\n");
32             else printf("No\n"); 
33         }
34     }
35     return 0;
36 }
37 
38 int sb=hh();
39 int main(int argc,char**argv) {;} 
代碼

 

六丶最長公共子括號序列

一個合法的括號匹配序列被定義為:
1. 空串""是合法的括號序列
2. 如果"X"和"Y"是合法的序列,那么"XY"也是一個合法的括號序列
3. 如果"X"是一個合法的序列,那么"(X)"也是一個合法的括號序列
4. 每個合法的括號序列都可以由上面的規則生成
例如"", "()", "()()()", "(()())", "(((()))"都是合法的。
從一個字符串S中移除零個或者多個字符得到的序列稱為S的子序列。
例如"abcde"的子序列有"abe","","abcde"等。
定義LCS(S,T)為字符串S和字符串T最長公共子序列的長度,即一個最長的序列W既是S的子序列也是T的子序列的長度。
小易給出一個合法的括號匹配序列s,小易希望你能找出具有以下特征的括號序列t:
1、t跟s不同,但是長度相同
2、t也是一個合法的括號匹配序列
3、LCS(s, t)是滿足上述兩個條件的t中最大的
因為這樣的t可能存在多個,小易需要你計算出滿足條件的t有多少個。

如樣例所示: s = "(())()",跟字符串s長度相同的合法括號匹配序列有:
"()(())", "((()))", "()()()", "(()())",其中LCS( "(())()", "()(())" )為4,其他三個都為5,所以輸出3.

思路:要求LCS最大 那么只改變一個位置的序列的LCS最大 

    每次只挖出一個字符 把它插入不同的位置 判斷是否為合法的序列 

     統計個數 最后再減去原序列

 

 1 #include <set>
 2 #include <cstdio>
 3 #include <cctype>
 4 #include <iostream>
 5 
 6 using namespace std;
 7 
 8 int len;
 9 
10 string s;
11 
12 set<string> Set;
13 
14 inline bool judge(string u) {
15     int q=0;
16     for(int i=0;i<len;++i) {
17         if(u[i]=='(') ++q;
18         else {
19             if(q==0) return false;
20             else --q;
21         }
22     }
23     if(!q) return true;
24     else return false;
25 }
26 
27 int hh() {
28     cin>>s;
29     len=s.length();
30     for(int i=0;i<len;++i) {
31         string p=s.substr(0,i)+s.substr(i+1);
32         for(int j=0;j<len-1;++j) {
33             string u=p.substr(0,j)+s[i]+p.substr(j);
34             if(judge(u)) Set.insert(u);
35         }
36     }
37     printf("%d\n",(int)Set.size()-1);
38     return 0;
39 }
40 
41 int sb=hh();
42 int main(int argc,char**argv) {;}
代碼

七丶合唱

小Q和牛博士合唱一首歌曲,這首歌曲由n個音調組成,每個音調由一個正整數表示。
對於每個音調要么由小Q演唱要么由牛博士演唱,對於一系列音調演唱的難度等於所有相鄰音調變化幅度之和, 例如一個音調序列是8, 8, 13, 12, 那么它的難度等於|8 - 8| + |13 - 8| + |12 - 13| = 6(其中||表示絕對值)。
現在要對把這n個音調分配給小Q或牛博士,讓他們演唱的難度之和最小,請你算算最小的難度和是多少。
如樣例所示: 小Q選擇演唱{5, 6}難度為1, 牛博士選擇演唱{1, 2, 1}難度為2,難度之和為3,這一個是最小難度和的方案了。

思路:動態規划 

   dp[i][j]表示 當前演唱到第i個音符 上一個人唱到第j個音符 的最小難度和 

轉移則為

dp[i][j] = dp[i-1][j] + abs(v[i] - v[i-1]), j < i - 1  (當前演唱者連續演唱第i-1個音符和第i個音符)
dp[i][i -1] = min{ dp[i-1][k] + abs(v[i] - v[k]) }, k < i - 1 (當前演唱者只唱第i個音符,第i-1個音符是由上一個人唱的)

 

邊界

一個人唱第一個音符 另一個人唱其他所有的音符 dp[i][0]=dp[i-1][0]+cost[i] (i>=2)

一個人唱前面的所有音符 另一個人唱最后一個音符 dp[i][i-1]=dp[i-1][i-2]+cost[i]  (i>=2) 

 1 #include <cstdio>
 2 #include <cctype>
 3 #include <cstdlib>
 4 #define min(a,b) a>b?b:a
 5 #define max(a,b) a>b?a:b
 6 
 7 typedef long long LL;
 8 
 9 const int MAXN=2010;
10 
11 int n;
12 
13 int a[MAXN],cost[MAXN];
14 
15 LL dp[MAXN][MAXN];
16 
17 inline void read(int&x) {
18     int f=1;register char c=getchar();
19     for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar());
20     for(;isdigit(c);x=x*10+c-48,c=getchar());
21     x=x*f;
22 }
23 
24 int hh() {
25     read(n);read(a[0]);
26     for(int i=1;i<n;++i) read(a[i]),cost[i]=abs(a[i]-a[i-1]);
27     
28     for(int i=2;i<n;++i) 
29       dp[i][0]=dp[i-1][0]+cost[i],
30       dp[i][i-1]=dp[i-1][i-2]+cost[i-1];
31     for(int i=2;i<n;++i) 
32       for(int j=0;j<i-1;++j) {
33           dp[i][j]=dp[i-1][j]+cost[i];
34           dp[i][i-1]=min(dp[i][i-1],dp[i-1][j]+abs(a[i]-a[j]));
35       }
36     LL ans=(1ll<<63)-1;
37     for(int i=0;i<n-1;++i) ans=min(ans,dp[n-1][i]);
38     
39     printf("%lld\n",ans);    
40     return 0;
41 }
42 
43 int sb=hh();
44 int main(int argc,char**argv) {;}
代碼

八丶射擊游戲

小易正在玩一款新出的射擊游戲,這個射擊游戲在一個二維平面進行,小易在坐標原點(0,0),平面上有n只怪物,每個怪物有所在的坐標(x[i], y[i])。小易進行一次射擊會把x軸和y軸上(包含坐標原點)的怪物一次性消滅。
小易是這個游戲的VIP玩家,他擁有兩項特權操作:
1、讓平面內的所有怪物同時向任意同一方向移動任意同一距離
2、讓平面內的所有怪物同時對於小易(0,0)旋轉任意同一角度
小易要進行一次射擊。小易在進行射擊前,可以使用這兩項特權操作任意次。

小易想知道在他射擊的時候最多可以同時消滅多少只怪物,請你幫幫小易。
 
如樣例所示:
所有點對於坐標原點(0,0)順時針或者逆時針旋轉45°,可以讓所有點都在坐標軸上,所以5個怪物都可以消滅。
思路:無論是操作一還是操作二 都不會發生相對位置的變化 
    n<=50 我們就有一個暴力枚舉的方法 
   枚舉兩個點 作為x軸 
    再找一個點 作x軸的垂線 作為y軸 構成一個新的坐標系 
     再枚舉有多少點在這個新的坐標系內 
     判斷垂直和平行兩種關系
 1 #include <cstdio>
 2 #include <cctype>
 3 
 4 const int MAXN=110;
 5 
 6 int n,ans;
 7 
 8 int x[MAXN],y[MAXN];
 9 
10 inline void read(int&x) {
11     int f=1;register char c=getchar();
12     for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar());
13     for(;isdigit(c);x=x*10+c-48,c=getchar());
14     x=x*f;
15 }
16 
17 int hh() {
18     read(n);
19     for(int i=1;i<=n;++i) read(x[i]);
20     for(int i=1;i<=n;++i) read(y[i]);
21     if(n<=3) {printf("%d\n",n);return 0;}
22     for(int i=1;i<=n;++i) 
23       for(int j=1;j<=n;++j) {
24           if(i==j) continue;
25           for(int k=1;k<=n;++k) {
26               if(k==i||k==j) continue;
27               int t=0;
28             for(int l=1;l<=n;++l) {
29                   if(l==k||l==i||l==j) continue;
30                   if((x[k]-x[l])*(x[j]-x[i])==(y[l]-y[k])*(y[j]-y[i])) ++t;
31                   else if((x[l]-x[i])*(y[l]-y[j])==(x[l]-x[j])*(y[l]-y[i])) ++t;
32             }
33             ans=t>ans?t:ans;
34         }
35       }
36     printf("%d\n",ans+3);
37     return 0;
38 }
39 
40 int sb=hh();
41 int main(int argc,char**argv) {;}
代碼

 


免責聲明!

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



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