1. 程式人生 > >程式設計之美---網易遊戲-2017實習筆試題

程式設計之美---網易遊戲-2017實習筆試題

編碼

 題目1:
給定一個字串,請你將字串重新編碼,將連續的字元替換成“連續
出現的個數+字元”。比如字串AAAABCCDAA會被編碼成4A1B2C1D2A。

.統計連續出現的字元數目.注意數字字串之間轉換,別要在這些細節上浪費太多時間,要不然後邊題沒時間做!程式碼:

#include<iostream>
#include<sstream>

int main()
{
  std::string s ;
  std::cin >> s;
  std::string res="";
  if(s==""){
    std::cout <<"";
    return
0; } // kong zi fu int cnt =1 ; for(int i =1 ; i< s.length(); i++) if(s[i-1]==s[i])cnt++; else { std::stringstream ss; std::string str; ss<<cnt; ss>>str; res = res + str + s[i-1]; cnt=1; } std::stringstream ss; std::string str; ss<<cnt; ss>>str; res = res +str +s[s.length()-1
]; std::cout <<res; return 0; }

簡單搜尋:

.題目2:
在一個N*N的陣列中尋找所有橫,豎,左上到右下,右上到左下,四種方向的直線連續D個數字的和裡面最大的值

分析

.可優化之處在於”連續” N 個數字和,N大於等於D,每次當和中包含的數字第一次大於N時,要想得到當前和,只需要減去上一次最後一個 
值再加上當前的值就可以了, 每次遍歷求和時間O(n),橫豎斜著遍歷去找就可,總時間O(n^2) 
考察程式設計熟練啊,被bug卡住就杯具了 
.程式碼;

#include<iostream>
#include<vector>
using std
::cin; using std::cout; using std::vector; using std::endl; int main() { /* 4 2 87 98 79 61 10 27 95 70 20 64 73 29 71 65 15 0 */ // input: int N , D; cin>>N>>D; vector<vector<int>> mm(N , vector<int>(N, 0)) ; for(int i =0 ; i< N ; i++) for(int j =0 ; j< N ; j++) cin>>mm[i][j]; int maxsum =0; for(int i =0 ; i < N ; i++) { int csum =0; for(int j =0 ; j < N ; j++) { csum = j < D? csum + mm[i][j] : csum + mm[i][j] - mm[i][j-D]; if(j>=D-1) maxsum = maxsum < csum? csum : maxsum; } csum =0 ; for(int j =0 ; j < N ; j++) { csum = j < D? csum + mm[j][i] : csum + mm[j][i] - mm[j-D][i]; if(j>=D-1) maxsum = maxsum < csum? csum : maxsum; } } int i = N-1 , j = 0; while(i>=0){ int m = i , n =j; int cnt =0; int csum =0; while(n<N&&m<N) { csum = cnt < D ? csum + mm[m][n]:csum+mm[m][n] - mm[m-D][n-D]; if(cnt>=D-1)maxsum = maxsum<csum? csum: maxsum; m++;n++;cnt++; } i--; } i = 0;j = 1; while(j<N) { int m = i , n = j; int cnt =0 ; int csum =0 ; while(m < N && n < N) { csum = cnt < D ? csum + mm[m][n] : csum+mm[m][n] - mm[m-D][n-D]; if(cnt >= D-1)maxsum = maxsum< csum?csum: maxsum; m++; n++;cnt++; } j++; } i =0 ; j = 0; while(j<N) { int m = i , n = j; int cnt =0; int csum =0 ; while(m<N&&n>=0) { csum = cnt < D ? csum +mm[m][n] : csum + mm[m][n] - mm[m-D][n+D]; if(cnt >= D-1) maxsum = maxsum < csum?csum:maxsum; m++;n--;cnt++; } j++; } i = 1; j =N-1; while(i < N) { int m = i , n = j; int cnt = 0; int csum = 0; while(m<N&&n>=0) { csum = cnt <D? csum + mm[m][n] :csum +mm[m][n] - mm[m-D][n+D]; if(cnt >= D-1) maxsum = maxsum <csum ? csum:maxsum; m++;n--;cnt++; } i++; } cout <<maxsum; return 0; }

推箱子

.題目3:
大家一定玩過“推箱子”這個經典的遊戲。具體規則就是在一個N*M的地
圖上,有1個玩家、1個箱子、1個目的地以及若干障礙,其餘是空地。
玩家可以往上下左右4個方向移動,但是不能移動出地圖或者移動到障
礙裡去。如果往這個方向移動推到了箱子,箱子也會按這個方向移動一
格,當然,箱子也不能被推出地圖或推到障礙裡。當箱子被推到目的地
以後,遊戲目標達成。現在告訴你遊戲開始是初始的地圖佈局,請你求
出玩家最少需要移動多少步才能夠將遊戲目標達成。
.輸入格式程式碼註釋裡有,*表示箱子,X表示人,@表示目的地,#表示障礙

分析

.後來做才發現這是寬度優先的題目,在一個圖結構當中如果每條邊權重是1的話,寬度優先搜尋第一次到達目的地步數就是到此位置的最小代價. 分析這道題最好的方式就是畫出狀態轉移關係,小人和箱子的位置確定了當前玩家的一個狀態,下一步要去往的狀態無非是這麼兩種情況: 
. 人走到另一個空地,箱子沒動 
.人推箱子前進一步

實現簡述

.宣告一個四位陣列來st,當前狀態表示為st[x][x][bx][bx]:人位
置(x,y),箱子位置(bx,by),並將初始位置陣列值設為1,將初始值壓
入一個佇列中
.每次從佇列中取出一個元素,寬度優先下一個未曾到達的狀態(以上分
析的兩種)判斷箱子是否到達終點.如果是列印路長並退出.
.沒有找到相關路徑列印-1.
#include<iostream>
#include<vector>
#include<queue>
using std::cin ;
using std::cout;
using std::vector;
using std::endl;
using std::queue;
/*
4 4
....
..*@
....
.X..
*/

int st[10][10][10][10];
int x,y,bx,by,tx,ty;
 int m ,  n ;
vector<vector<char>> mm ;

bool valid(int x,int y ){
  //cout <<m<<" "<<n<<"-"<<endl;
   if(x>=0&&x<m&&y>=0&&y<n&&mm[x][y]!='#')return true;
   return false;
}

int main(){

   cin >> m >>n;
   mm= vector<vector<char>>(m , vector<char>(n ,' ' ));

   for(int i =0 ; i < m ; i++)
     for(int j=0 ; j< n ; j++)
    {
        char t ;
        cin >>t;
        if(t=='X'){
          x = i;y = j;
         // cout <<x<<" "<<y<<endl;
        }
        if(t == '*'){
           bx = i ;by = j;
         }
        if(t == '@'){
          tx = i ; ty = j;
        }
        mm[i][j] = t;           
    } 

//  record every state of the 
  vector<vector<int>> next= {{-1, 0},{1,0},{0,1},{0,-1}};
  queue<vector<int>> que ;
  que.push({x,y,bx,by});

  st[x][y][bx][by] =1 ;
  while(!que.empty())
  {
      vector<int> t = que.front();
      que.pop();
      x =  t[0];  y = t[1];  bx=t[2]; by = t[3];
      for(int i =0 ; i < next.size() ; i++)
      {
         int nx = x+next[i][0],ny =y+next[i][1]; 
         int nnx = nx+next[i][0],nny =ny+next[i][1]; 
         if(valid(nx,ny)&&(nx!=bx||ny!=by)&&st[nx][ny][bx][by]==0)
         {
             st[nx][ny][bx][by]= st[x][y][bx][by]+1;
             que.push({nx,ny,bx,by});
             continue;

         }else if(nx==bx&&ny==by&&valid(nnx,nny)&&st[nx][ny][nnx][nny]==0){ 
              st[nx][ny][nnx][nny] = st[x][y][bx][by]+1;
              if(mm[nnx][nny]=='@'){cout<<st[nx][ny][nnx][nny]-1;return 0;}
              que.push({nx,ny,nnx,nny});
          }
      }
  } 

   cout <<-1;
   return 0;
}

賽馬

.題目4:
在一條無限長的跑道上,有N匹馬在不同的位置上出發開始賽馬。當開
始賽馬比賽後,所有的馬開始以自己的速度一直勻速前進。每匹馬的速
度都不一樣,且全部是同樣的均勻隨機分佈。在比賽中當某匹馬追上了
前面的某匹馬時,被追上的馬就出局。 請問按以上的規則比賽無限長
的時間後,賽道上剩餘的馬匹數量的數學期望是多少

分析

.開始認為幾匹快馬速度一樣才可能同時留下來,沒好好讀題,其實人家說了馬的速度都不一樣.假設幾匹馬的速度是a1<a2<a3<...<ana1<a2<a3<...<an ,ai匹馬留下概率是P(i),Pi=1/iP(i)=1/i, 因為只有在第一匹快馬後面才能留下來,這是i種情況之一, 第i匹馬留下期望0(i1)/i+1/i0∗(i−1)/i+1/i,由E(X+Y)=E(X)+E(Y)E(X+Y)=E(X)+E(Y)得到所有馬期望和1 + 1 / 2 + 1 / 3 + 1 / 4 + … + 1 / N,就是調和級數。

#include<iostream>
#include<stdio.h>
#include<math.h>
using std::cin;
using std::cout;

int main(){

int n ;
cin >>n;
if(n==0)
{
 cout <<0;
 return 0;
}
float sum =0.0;
for(int i =1 ; i<=n ; i++)
{
  sum+= 1.0/i;
}
printf("%.4f",sum);

return 0;
}