微软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,

扫描二维码关注公众号,回复: 3848920 查看本文章

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;
}

猜你喜欢

转载自blog.csdn.net/dyx404514/article/details/51079237