微软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这种事
第二题:先给N个字符串allow或deny,然后是一段ip,点分十进制的形式。后面可能会有掩码位数。然后给M个字符串表示ip(无掩码),如果能找到与上面符合的,allow输出YES,deny输出NO,找不到也输出YES。符合是指化成二进制后前掩码位数的数字相同。如果有多个匹配以第一个为标准。
题解:很容易想到字典树,可惜实在是太弱,写了好久,还好是1A。先预处理出0~255的二进制。然后把每个ip化成字符串,几位掩码字符串就截断到几位,否则就是32位。
第三题:一个机器人只会向右走和向下走,碰到墙才会转弯,问至少改变几块墙(即墙变为空地或空地变为墙),使机器人可以从左上角走到右下角。一开始的方向是向右。
题解:一眼就想到dp,dp[i][j][k]表示从(0,0)走到(i,j)且方向是k的最少花费。k为0表示向右,k为1表示向下。可惜转移那里想了很久,就是有点蒙,重复考虑了一些情况,代码写的比较慢(主要是第二题浪费了太多时间),总之就是没来的提交,赛后A的。
对于每一个点都有向下和向右两种情况,每一种情况都有可能是从左边和上边转移过来的。比如向下的可能是下面两种情况,向右同理。
第四题没做。。。。。跪、、、
总之就是GG了。。。。
第一题:输入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了。。。。
相关文章推荐
- 检测通过什么平台打开网站
- import static
- [na][tools]快速ping网段工具-QuickPing
- 构建之法学习心得(需求分析,IT行业的创新)
- 用MFC实现静态文本超链接的方法 及静态文本颜色
- [转]MyBatis传入多个参数的问题 - mingyue1818
- What are Groups for Office 365?
- 如何在Linux上安装服务器管理软件Cockpit
- KindEditor得不到textarea值的解决方法
- C++ GET UTF-8网页编码转换
- [转]MyBatis传入多个参数的问题 - mingyue1818
- php 下载图片
- 匿名内部类
- Source insight安装使用相关问题解决方案
- 生成螺旋矩阵(方阵、矩阵)
- nginx 中的ctx什么意思
- Docker问题(Get http:///var/run/docker.sock/v1.20/version:dial unix /var/run/docker.sock: no such file)
- iso中第三方框架SDWebImage的使用步骤
- 主流操作系统、浏览器DNS缓存时间
- 第二次试验