微軟2016校園招聘4月在線筆試 總結

今天參加了微軟實習筆試,有點慘烈。。,題目看錯WA了一堆導致後期時間 不夠。。。最後一題沒時間仔細想只能暴力騙分。先來前三題的總結吧。
題目鏈接:題目1 : Font Size

描述
Steven loves reading book on his phone. The book he reads now consists of N paragraphs and the i-th paragraph contains ai characters.

Steven wants to make the characters easier to read, so he decides to increase the font size of characters. But the size of Steven’s phone screen is limited. Its width is W and height is H. As a result, if the font size of characters is S then it can only show ⌊W / S⌋ characters in a line and ⌊H / S⌋ lines in a page. (⌊x⌋ is the largest integer no more than x)

So here’s the question, if Steven wants to control the number of pages no more than P, what’s the maximum font size he can set? Note that paragraphs must start in a new line and there is no empty line between paragraphs.

輸入
Input may contain multiple test cases.

The first line is an integer TASKS, representing the number of test cases.

For each test case, the first line contains four integers N, P, W and H, as described above.

The second line contains N integers a1, a2, … aN, indicating the number of characters in each paragraph.

For all test cases,

1 <= N <= 103,

1 <= W, H, ai <= 103,

1 <= P <= 106,

There is always a way to control the number of pages no more than P.

輸出
For each testcase, output a line with an integer Ans, indicating the maximum font size Steven can set.

題目很簡單,直接二分字體大小,然後判斷這種字體下要使用多少行,最後轉換成頁面就行。唯一需要注意的就是不同的paragraph之間需要換行,不能直接根據文字總量計算。題目比較簡單直接,就不多說了。代碼如下:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <vector>
#define maxn 100010
#define ll long long
using namespace std;
int a[maxn];
int main()
{
    //freopen("dd.txt","r",stdin);
    int ncase;
    scanf("%d",&ncase);
    while(ncase--){
        int n,p,w,h;
        scanf("%d%d%d%d",&n,&p,&w,&h);
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
        }
        int mi=1,ma=min(w,h),mid,ans;
        while(mi<=ma){
            mid=(mi+ma)/2;
            int tmp=0;
            for(int i=0;i<n;i++){
                int num=w/mid;
                tmp+=(a[i]+num-1)/num;
            }
            int height=h/mid;
            int page=(tmp+height-1)/height;
            if(page<=p){
                ans=mid;
                mi=mid+1;
            }
            else
                ma=mid-1;
        }
        printf("%d\n",ans);
    }
    return 0;
}

題目2 : 403 Forbidden

描述:
Little Hi runs a web server. Sometimes he has to deny access from a certain set of malicious IP addresses while his friends are still allow to access his server. To do this he writes N rules in the configuration file which look like:

allow 1.2.3.4/30
deny 1.1.1.1
allow 127.0.0.1
allow 123.234.12.23/3
deny 0.0.0.0/0
Each rule is in the form: allow | deny address or allow | deny address/mask.

When there comes a request, the rules are checked in sequence until the first match is found. If no rule is matched the request will be allowed. Rule and request are matched if the request address is the same as the rule address or they share the same first mask digits when both written as 32bit binary number.

For example IP “1.2.3.4” matches rule “allow 1.2.3.4” because the addresses are the same. And IP “128.127.8.125” matches rule “deny 128.127.4.100/20” because 10000000011111110000010001100100 (128.127.4.100 as binary number) shares the first 20 (mask) digits with 10000000011111110000100001111101 (128.127.8.125 as binary number).

Now comes M access requests. Given their IP addresses, your task is to find out which ones are allowed and which ones are denied.

輸入
Line 1: two integers N and M.

Line 2-N+1: one rule on each line.

Line N+2-N+M+1: one IP address on each line.

All addresses are IPv4 addresses(0.0.0.0 - 255.255.255.255). 0 <= mask <= 32.

For 40% of the data: 1 <= N, M <= 1000.

For 100% of the data: 1 <= N, M <= 100000.

輸出
For each request output “YES” or “NO” according to whether it is allowed.

雪崩題,就因爲這道WA了半天浪費了好多時間。首先題意要明確,主要的幾個Trick就是
1:IP是要匹配最早的規則,而不是最長的
2:如果一個IP沒有匹配的規則也要輸出yes
3:小Hi給出的規則可能有矛盾,要看最早的而不是最後的規則(因爲第一條)。

很容易看出是一個 Trie樹的問題,因爲需要考慮時間的問題,在字典樹節點中加入time表示更新flag的時間。根據規則往Trie樹中插入IP,並更新flag(allow或deny,注意要保留時間較早的狀態),對於一個IP requests, 在樹中從根節點到葉子節點的途中,保留時間最早的狀態,如果沒有,則輸出YES,否則根據狀態判斷是否接受。 代碼如下:(由於筆試中 這題WA了很久,心態有點崩,代碼長度爆炸,明天有時間可以精簡一下)

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <vector>
#define maxn 2000010
#define ll long long
using namespace std;
struct trie{
    int flag,time;
    int go[2];
    void init(){
        flag=0;
        go[0]=go[1]=0;
        time=20000000;
    }
}node[maxn];
int tot,n,m,root;
int getIP(char *str,vector<int> &vec){
    int len=strlen(str);
    int num=0,tru=0;
    for(int i=0;i<len;i++){
        if(str[i]=='.'){
            for(int j=7;j>=0;j--){
                if(num&(1<<j))
                    vec.push_back(1);
                else
                    vec.push_back(0);
            }
            num=0;
        }
        else if(str[i]=='/'){
            for(int j=7;j>=0;j--){
                if(num&(1<<j))
                    vec.push_back(1);
                else
                    vec.push_back(0);
            }
            num=0;
            tru=1;
        }
        else{
            num=num*10+str[i]-'0';
        }
    }
    if(tru){
        return num;
    }
    else{
        for(int j=7;j>=0;j--){
            if(num&(1<<j))
                vec.push_back(1);
            else
                vec.push_back(0);
        }
        return vec.size();
    }
}
void insert(char *str,int flag,int time){
    vector<int> vec;
    int len=getIP(str,vec);
    int p=1;
    for(int i=0;i<len;i++){
        int id=vec[i];
        if(node[p].go[id]==0){
            node[++tot].init();
            node[p].go[id]=tot;
        }
        p=node[p].go[id];
    }
    if(node[p].flag==0){//保留時間較早的狀態
        node[p].flag=flag;
        node[p].time=time;
    }
}
bool ck(char *str){
    vector<int> vec;
    int len=getIP(str,vec);
    int p=1;
    int statu=0,T=20000000;
    for(int i=0;i<len;i++){
        if(node[p].flag!=0){
            if(node[p].time<T){
                T=node[p].time;
                statu=node[p].flag;
            }
        }
        int id=vec[i];
        if(node[p].go[id]==0)
            return statu!=-1;
        p=node[p].go[id];
    }
    if(node[p].time<T)
        statu=node[p].flag;
    return statu!=-1;
}
int main()
{
    //freopen("dd.txt","r",stdin);
    int n,m;
    scanf("%d%d",&n,&m);
    tot=0;
    root=++tot;
    node[root].init();
    for(int i=0;i<n;i++){
        char op[10],str[20];
        scanf("%s%s",op,str);
        if(op[0]=='a'){
            insert(str,1,i);
        }
        else{
            insert(str,-1,i);
        }
    }
    for(int i=0;i<m;i++){
        char str[20];
        scanf("%s",str);
        if(ck(str)){
            printf("YES\n");
        }
        else
            printf("NO\n");
    }
    return 0;
}

題目3 : Demo Day

描述
You work as an intern at a robotics startup. Today is your company’s demo day. During the demo your company’s robot will be put in a maze and without any information about the maze, it should be able to find a way out.

The maze consists of N * M grids. Each grid is either empty(represented by ‘.’) or blocked by an obstacle(represented by ‘b’). The robot will be release at the top left corner and the exit is at the bottom right corner.

Unfortunately some sensors on the robot go crazy just before the demo starts. As a result, the robot can only repeats two operations alternatively: keep moving to the right until it can’t and keep moving to the bottom until it can’t. At the beginning, the robot keeps moving to the right.

rrrrbb..
…r…. ====> The robot route with broken sensors is marked by ‘r’.
…rrb..
…bb…
While the FTEs(full-time employees) are busy working on the sensors, you try to save the demo day by rearranging the maze in such a way that even with the broken sensors the robot can reach the exit successfully. You can change a grid from empty to blocked and vice versa. So as not to arouse suspision, you want to change as few grids as possible. What is the mininum number?

輸入
Line 1: N, M.

Line 2-N+1: the N * M maze.

For 20% of the data, N * M <= 16.

For 50% of the data, 1 <= N, M <= 8.

For 100% of the data, 1<= N, M <= 100.

應該很容易看出是一個動態規劃,由於機器人交替向右走向下走。所以設dp[i][j][0]表示到達點(i,j)停下來,並且下一次運動是向右移動最少需要改變的格子數量。 dp[i][j][1]表示到達點 (i,j)停下來,並且下一次運動是向下移動最少需要改變的格子數量。

那麼轉移很簡單,對於 dp[i][j][0],由於它下一次移動是向右邊的,所以它上一次移動就是向下,
所以考慮dp[k][j][1] (其中 0< k < i),
那麼 dp[i][j][0]= min(dp[k][j][1]+bnum),其中bnum表示從點 (k,j)到點 (i,j)遇到的障礙數(也就是 ‘b’的數量)。

那麼同理對 dp[i][j][1]也可以用同樣的方法求得,一個要注意的就是,對於dp[i][j][0],如果點(i+1,j)沒有障礙,那麼最後還需要將dp[i][j][0]加上1,這是因爲我要停在點(i,j)上的話,我需要一個障礙讓我停住對吧,對於dp[i][j][1]同理,最後輸出 dp[n][m][0]和dp[n][m][1]的較小值即爲答案。代碼如下:

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <vector>
using namespace std;
int dp[110][110][2];
char mp[110][110];
int main()
{
    //freopen("dd.txt","r",stdin);
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%s",mp[i]+1);

    dp[1][1][0]=mp[1][1]=='b';
    dp[1][1][1]=(mp[1][1]=='b')+mp[1][2]!='b';

    for(int i=1;i<=m;i++)
        mp[n+1][i]='b';
    for(int i=1;i<=n;i++)
        mp[i][m+1]='b';
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(i==1&&j==1)
                continue;
            int up=2000,left=2000,tmp=0;
            for(int k=i-1;k>0;k--){
                up=min(up,dp[k][j][1]+tmp);
                if(mp[k][j]=='b')
                    tmp++;
            }
            tmp=0;
            for(int k=j-1;k>0;k--){
                left=min(left,dp[i][k][0]+tmp);
                if(mp[i][k]=='b')
                    tmp++;
            }
            if(mp[i][j]=='b')
                left++,up++;
            if(mp[i][j+1]!='b')
                left++;
            if(mp[i+1][j]!='b')
                up++;
            dp[i][j][0]=up;
            dp[i][j][1]=left;
        }
    }
    printf("%d\n",min(dp[n][m][0],dp[n][m][1]));
    return 0;
}

#1291 : Buiding in Sandbox

描述
Little Hi is playing a sandbox voxel game. In the game the whole world is constructed by massive 1x1x1 cubes. The edges of cubes are parallel to the coordinate axes and the coordinates (x, y, z) of the center of each cube are integers.
At the beginning there is nothing but plane ground in the world. The ground consists of all the cubes of z=0. Little Hi needs to build everything by placing cubes one by one following the rules:

  1. The newly placed cube must be adjacent to the ground or a previously placed cube. Two cubes are adjacent if and only if they share a same face.

  2. The newly placed cube must be accessible from outside which means by moving in 6 directions(up, down, left, right, forward, backward) there is a path from a very far place - say (1000, 1000, 1000) in this problem - to this cube without passing through ground or other cubes.

Given a sequence of cubes Little Hi wants to know if he can build the world by placing the cubes in such order.

輸入
The first line contains the number of test cases T(1 <= T <= 10).

For each test case the first line is N the number of cubes in the sequence.

The following N lines each contain three integers x, y and z indicating the coordinates of a cube.

For 20% of the data, 1 <= N <= 1000, 1 <= x, y, z <= 10.

For 100% of the data, 1 <= N <= 100000, 1 <= x, y, z <= 100.

輸出
For each testcase output “Yes” or “No” indicating if Little Hi can place the cubes in such order.

(4.9更新)
拖了兩天,今天來補完吧。。。還是挺簡單的。
首先第一個條件很好判斷,用一個三維數組記錄之前出現過的方塊位置,然後新加入一個方塊的時候判斷其前後左右是否存在方塊就行,注意地面(z==0)已經鋪滿方塊。
然後對於第二個條件。可以從後往前做,首先將所有方塊位置記錄一下,然後從一個很遠的位置,比如T(101,101,101)進行搜索,將它可到達的位置記錄下來(不經過任何方塊,用一個數組vis記錄),然後從後往前遍歷每個方塊,查看其前後左右是否存在T可達的點,如果不存在則直接輸出No,否則,繼續遍歷,注意當我們遍歷完一個方塊後,要將他消除,並且把它設爲T可到達的點。 具體可參考以下代碼:

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <queue>
using namespace std;
int mp[110][110][110],vis[110][110][110];
int X[100010],Y[100010],Z[100010];
int dir[6][3]={1,0,0,0,1,0,0,0,1,-1,0,0,0,-1,0,0,0,-1};
inline int Abs(int x){
    return x<0?-x:x;
}
bool check(int x,int y,int z){
    if(x<0||y<0||z<1||x>=102||y>=102||z>=102||mp[x][y][z])
        return false;
    return true;
}
queue<int> q;
void bfs(int x,int y,int z){
    vis[x][y][z]=1;
    q.push(x);
    q.push(y);
    q.push(z);
    while(!q.empty()){
        int x=q.front();q.pop();
        int y=q.front();q.pop();
        int z=q.front();q.pop();
        for(int i=0;i<6;i++){
            int xx=dir[i][0]+x,yy=y+dir[i][1],zz=z+dir[i][2];
            if(check(xx,yy,zz)&&vis[xx][yy][zz]==0){
                vis[xx][yy][zz]=1;
                q.push(xx);
                q.push(yy);
                q.push(zz);
            }
        }
    }
}
bool ck(int n){
    for(int i=0;i<n;i++){
        int flag=0;
        for(int d=0;d<6;d++){
            int x=X[i]+dir[d][0],y=Y[i]+dir[d][1],z=Z[i]+dir[d][2];
            if(z==0||mp[x][y][z]){
                flag=1;
                break;
            }
        }
        if(!flag)
            return false;
        mp[X[i]][Y[i]][Z[i]]++;
    }
    bfs(101,101,101);
    for(int i=n-1;i>=0;i--){
        int x=X[i],y=Y[i],z=Z[i];
        int tru=0;
        mp[x][y][z]--;
        for(int d=0;d<6;d++){
            int xx=x+dir[d][0],yy=y+dir[d][1],zz=z+dir[d][2];
            if(check(xx,yy,zz)&&vis[xx][yy][zz]){
                tru=1;
                break;
            }
        }
        if(mp[x][y][z]==0)
            vis[x][y][z]=1;
        if(!tru)
            return false;
    }
    return true;
}
int main()
{
    //freopen("dd.txt","r",stdin);
    int ncase;
    scanf("%d",&ncase);
    while(ncase--){
        int n;
        scanf("%d",&n);
        memset(vis,0,sizeof(vis));
        memset(mp,0,sizeof(mp));
        int px,py,pz;
        for(int i=0;i<n;i++){
            scanf("%d%d%d",&X[i],&Y[i],&Z[i]);
        }
        if(ck(n))
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章