您的位置:首页 > 其它

微软2016校园招聘4月在线笔试 ABC

2016-04-07 10:13 190 查看
题目链接:http://hihocoder.com/contest/mstest2016april1/problems

第一题:输入N,P,W,H,代表有N段文字,每段有ai个字,每行有⌊W/S⌋个字,每页有⌊H/S⌋行,每段结束换行,希望总页数不超过P,求最大的S。

题解: 没什么好说的,本来想二分S,结果发现N才1000,直接暴力。0ms过的。【我才不会说交错语言CE这种事

#include <cstdio>
#include <cmath>
using namespace std;
int a[1005];
int main()
{
int t;
int n, w, h, p;
scanf("%d", &t);
while (t--) {
scanf("%d%d%d%d", &n, &p, &w, &h);
for (int i = 0; i < n; ++i) scanf("%d", a + i);
for (int s = w; s > 0; --s) {
int cnt = 0;
for (int i = 0; i < n; ++i) {
cnt += ceil((double)a[i] / floor((double)w / s));
}
if (ceil((double)cnt / floor((double)h / s)) <= p) {
printf("%d\n", s);
break;
}
}

}
return 0;
}


第二题:先给N个字符串allow或deny,然后是一段ip,点分十进制的形式。后面可能会有掩码位数。然后给M个字符串表示ip(无掩码),如果能找到与上面符合的,allow输出YES,deny输出NO,找不到也输出YES。符合是指化成二进制后前掩码位数的数字相同。如果有多个匹配以第一个为标准。

题解:很容易想到字典树,可惜实在是太弱,写了好久,还好是1A。先预处理出0~255的二进制。然后把每个ip化成字符串,几位掩码字符串就截断到几位,否则就是32位。

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int KIND = 2;
const int MAXN = 3200010;
int cnt_node;

struct node{
node* nt[2];
int flag;
int cnt;
void init(){
memset(nt, 0, sizeof(nt));
flag = -1;
cnt = 0;
}
} Heap[MAXN];

inline node* new_node()
{
Heap[cnt_node].init();
return &Heap[cnt_node++];
}

void insert(node* root, char *str, int flag, int cnt)
{
for(char *p = str; *p; ++p){
int ch = *p - '0';
if(root->nt[ch] == NULL)
root->nt[ch] = new_node();
root = root->nt[ch];
}
if (root->flag == -1) {
root->flag = flag;
root->cnt = cnt;
}
}

int count(node* root, char *str)
{
int cnt = 1000000;;
int ans = -1; //printf("flag - %d\n", root->flag);
if(root->flag != -1 && root->cnt < cnt) {
cnt = root->cnt;
ans = root->flag;

}
for(char *p = str; *p; ++p){
int ch = *p - '0';
if(root->nt[ch] == NULL) {
return ans;
}
root = root->nt[ch];
if(root->flag != -1 && root->cnt < cnt) {
cnt = root->cnt;
ans = root->flag;
}
}
return ans;
}

int num[300][10];
void init()
{
for (int i = 0; i <= 255; i++) {
for (int j = 0; j < 8; j++) {
if (i & (1 << j)) num[i][8 - j - 1] = 1;
}
}
//    for (int i = 0; i < 20; ++i) {
//        for (int j = 0; j < 8; ++j)
//            printf("%d", num[i][j]); printf("\n");
//    }
}
//10000000 01111111 0000/1000 01111101 128.127.8.125/20

void input(char *s)
{
int a[4], mark = 32;
scanf("%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]);
//printf("%d %d %d %d", a[0], a[1], a[2], a[3]);
char ch;
scanf("%c", &ch);
if (ch == '/') scanf("%d", &mark);

for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 8; ++j) {
s[i * 8 + j] = num[ a[i] ][j] + '0';
}
}
s[mark] = 0;
//printf(" s = %s\n", s);
}

int main()
{
init();
int n, m;
while(scanf("%d%d", &n, &m) != EOF)
{
cnt_node = 0;
node *root = new_node();
char s[50], op[50];
for (int i = 0; i < n; ++i) {
scanf("%s", op);
input(s);
//printf("%s\n", s);
insert(root, s, *op == 'a' ? 1 : 2, i);
}
for (int i = 0; i < m; ++i) {
input(s);
//printf("%s\n", s);
if (count(root, s) == -1 || count(root, s) == 1) printf("YES\n");
else printf("NO\n");
}
}
return 0;
}


第三题:一个机器人只会向右走和向下走,碰到墙才会转弯,问至少改变几块墙(即墙变为空地或空地变为墙),使机器人可以从左上角走到右下角。一开始的方向是向右。

题解:一眼就想到dp,dp[i][j][k]表示从(0,0)走到(i,j)且方向是k的最少花费。k为0表示向右,k为1表示向下。可惜转移那里想了很久,就是有点蒙,重复考虑了一些情况,代码写的比较慢(主要是第二题浪费了太多时间),总之就是没来的提交,赛后A的。

对于每一个点都有向下和向右两种情况,每一种情况都有可能是从左边和上边转移过来的。比如向下的可能是下面两种情况,向右同理。





#include <cstdio>
#include <algorithm>
using namespace std;
char mp[105][105];
int dp[105][105][2];
int n, m;

int isWall(int i, int j) { if (i == n || j == m || mp[i][j] == 'b') return 1; return 0; }
int notWall(int i, int j) { if (i == n || j == m || mp[i][j] == 'b') return 0; return 1; }

int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n; ++i) scanf("%s", mp[i]);

for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (i == 0) {
if (j == 0) {
dp[i][j][0] = 0;
dp[i][j][1] = notWall(i, j+1);
} else {
dp[i][j][0] = dp[i][j-1][0];
dp[i][j][1] = dp[i][j-1][0] + notWall(i, j+1);
}
} else {
if (j == 0) {
dp[i][j][0] = dp[i-1][j][1] + notWall(i+1, j);
dp[i][j][1] = dp[i-1][j][1];
} else {
dp[i][j][0] = min(dp[i][j-1][0], dp[i-1][j][1] + notWall(i+1, j));
dp[i][j][1] = min(dp[i-1][j][1], dp[i][j-1][0] + notWall(i, j+1));
}
}

dp[i][j][0] += isWall(i, j);
dp[i][j][1] += isWall(i, j);
}
}
printf("%d\n", min(dp[n - 1][m - 1][0], dp[n-1][m-1][1]));
return 0;
}


第四题没做。。。。。跪、、、

总之就是GG了。。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: