微软2016校园招聘笔试(第一场) Professor Q's Software & Recruitment
来源:互联网 发布:python服务器搭建 编辑:程序博客网 时间:2024/05/18 03:38
为什么只有这两个题的题解?因为师兄只让我看了这两个题。。
题目链接:
Professor Q's Software
Recruitment
#1136 : Professor Q's Software
- 样例输入
33 2123 256123 2 456 256456 3 666 111 256256 1 903 1100100 2 200 200200 1 300200 05 111 2 2 32 2 3 43 2 4 54 2 5 65 2 6 7
- 样例输出
1 1 31 2 21 1 2 3 5
描述
Professor Q develops a new software. The software consists of N modules which are numbered from 1 to N. The i-th module will be started up by signal Si. If signal Si is generated multiple times, the i-th module will also be started multiple times. Two different modules may be started up by the same signal. During its lifecircle, the i-th module will generate Ki signals: E1, E2, ..., EKi. These signals may start up other modules and so on. Fortunately the software is so carefully designed that there is no loop in the starting chain of modules, which means eventually all the modules will be stoped. Professor Q generates some initial signals and want to know how many times each module is started.
输入
The first line contains an integer T, the number of test cases. T test cases follows.
For each test case, the first line contains contains two numbers N and M, indicating the number of modules and number of signals that Professor Q generates initially.
The second line contains M integers, indicating the signals that Professor Q generates initially.
Line 3~N + 2, each line describes an module, following the format S, K, E1, E2, ... , EK. S represents the signal that start up this module. K represents the total amount of signals that are generated during the lifecircle of this module. And E1 ... EK are these signals.
For 20% data, all N, M <= 10
For 40% data, all N, M <= 103
For 100% data, all 1 <= T <= 5, N, M <= 105, 0 <= K <= 3, 0 <= S, E <= 105.
Hint: HUGE input in this problem. Fast IO such as scanf and BufferedReader are recommended.
输出
For each test case, output a line with N numbers Ans1, Ans2, ... , AnsN. Ansi is the number of times that the i-th module is started. In case the answers may be too large, output the answers modulo 142857 (the remainder of division by 142857).
开始想dp或者数据结构胡搞。。后来发现是个拓扑排序裸题。。
思路:
分析题目后发现每个点集是个有向无环图,所以直接拓扑排序得出点的顺序,因为排序后相连点的顺序在该点之后,所以可以dp一下。
需要注意的是,虽然dfs拓扑排序复杂度是O(VE)的,但是E是和每个点的相连的边,题目里说了最多3条边,所以可以用这种方法,而O(V^2)的拓扑排序就显然不行。
AC代码:
#include <cstdio>#include <cstring>#include <vector>#include <stack>using namespace std;const int MOD = 142857;const int M = 100020;int sig[M], idx[M];bool vis[M];vector<int> module[M];stack<int> stk;bool dfs(int now) {//dfs vis[now] = -1; for(int i = 0; i < module[now].size(); i++) { if(vis[module[now][i]] == -1) return false; else if(vis[module[now][i]] == 0) { dfs(module[now][i]); } } vis[now] = 1; stk.push(now); return true;}bool toposort() {//拓扑排序 memset(vis, 0, sizeof vis); for(int i = 0; i < M; i++) { if(vis[i] == 0) { if(dfs(i) == false) return false; } } return true;}main() { int T; scanf("%d", &T); while(T--) { memset(sig, 0, sizeof sig); int n, m; scanf("%d %d", &n, &m); for(int i = 0; i < n; i++) module[i].clear(); for(int i = 0; i < m; i++) { int a; scanf("%d", &a); sig[a]++; } for(int i = 0; i < n; i++) { int signal, p; scanf("%d %d", &signal, &p); idx[i] = signal; for(int j = 0; j < p; j++) { int a; scanf("%d", &a); module[signal].push_back(a); } } if(toposort()) {//dp while(!stk.empty()) { int signal = stk.top(); stk.pop(); for(int i = 0; i < module[signal].size(); i++) { sig[module[signal][i]] += sig[signal]; sig[module[signal][i]] %= MOD; } } } printf("%d", sig[idx[0]]); for(int i = 1; i < n; i++) printf(" %d", sig[idx[i]]); putchar('\n'); }}
#1137 : Recruitment
- 样例输入
4 1 1 10F 2 3M 7 6M 3 2F 9 9
- 样例输出
9 91 2
描述
A company plans to recruit some new employees. There are N candidates (indexed from 1 to N) have taken the recruitment examination. After the examination, the well-estimated ability value as well as the expected salary per year of each candidate is collected by the Human Resource Department.
Now the company need to choose their new employees according to these data. To maximize the company's benefits, some principles should be followed:
1. There should be exactly X males and Y females.
2. The sum of salaries per year of the chosen candidates should not exceed the given budget B.
3. The sum of ability values of the chosen candidates should be maximum, without breaking the previous principles. Based on this, the sum of the salary per year should be minimum.
4. If there are multiple answers, choose the lexicographically smallest one. In other words, you should minimize the smallest index of the chosen candidates; If there are still multiple answers, then minimize the second smallest index; If still multiple answers, then minimize the third smallest one; ...
Your task is to help the company choose the new employees from those candidates.
输入
The first line contains four integers N, X, Y, and B, separated by a single space. The meanings of all these variables are showed in the description above. 1 <= N <= 100, 0 <= X <= N, 0 <= Y <= N, 1 <= X + Y <= N, 1 <= B <= 1000.
Then follows N lines. The i-th line contains the data of the i-th candidate: a character G, and two integers V and S, separated by a single space. G indicates the gender (either "M" for male, or "F" for female), V is the well-estimated ability value and S is the expected salary per year of this candidate. 1 <= V <= 10000, 0 <= S <= 10.
We assure that there is always at least one possible answer.
输出
On the first line, output the sum of ability values and the sum of salaries per year of the chosen candidates, separated by a single space.
On the second line, output the indexes of the chosen candidates in ascending order, separated by a single space.
思路:男女分别dp,然后匹配。
做两个dp,dpf[i][j]表示所有女性中选i个,工资为j时的价值,dpm[i][j]表示所有男性中选i个,工资为j时的价值;fidx[i][j][0],i j表示之前的dpf[i][j],0是所有应聘人的前50个,1是后50个,这是个long long数组, 利用位运算来标记对应i j选了哪些人,midx同理。
设要选female个女性,male个男性,对所有的dpf[female][i]和dpm[male][j]匹配,根据题意选出B以下价值最大工资最低字典序最靠前的。
AC代码:
#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;int dpf[105][1005], dpm[105][1005];unsigned long long fidx[105][1005][2];unsigned long long midx[105][1005][2];main() { int n, male, female, b; while(~scanf("%d %d %d %d", &n, &male, &female, &b)) { memset(dpf, -1, sizeof dpf); memset(dpm, -1, sizeof dpm); memset(fidx, 0, sizeof fidx); memset(midx, 0, sizeof midx); dpf[0][0] = dpm[0][0] = 0; int cntm = 0, cntf = 0, sum = 0; for(int i = 1; i <= n; i++) { char str[2]; int v, c; scanf("%s %d %d", str, &v, &c); sum += c; sum = min(sum, b); if(str[0] == 'F') { cntf++; cntf = min(cntf, female); for(int j = cntf; j >= 1; j--) {//dp女性 for(int k = sum; k >= c; k--){ if(dpf[j - 1][k - c] < 0) continue; if(dpf[j - 1][k - c] + v > dpf[j][k]) { dpf[j][k] = dpf[j - 1][k - c] + v; fidx[j][k][0] = fidx[j - 1][k - c][0], fidx[j][k][1] = fidx[j - 1][k - c][1]; if(i - 1 < 50) fidx[j][k][0] |= 1LL << (i - 1); else fidx[j][k][1] |= 1LL << (i - 1 - 50); // printf("dpf %d %d %d %d %d\n", j, k, i, fidx[j][k][0], fidx[j][k][1]); } } } } else { cntm++; cntm = min(cntm, male); for(int j = cntm; j >= 1; j--) {//dp男性 for(int k = sum; k >= c; k--){ if(dpm[j - 1][k - c] < 0) continue; if(dpm[j - 1][k - c] + v > dpm[j][k]) { dpm[j][k] = dpm[j - 1][k - c] + v; midx[j][k][0] = midx[j - 1][k - c][0], midx[j][k][1] = midx[j - 1][k - c][1]; if(i - 1< 50) midx[j][k][0] |= 1LL << (i - 1); else midx[j][k][1] |= 1LL << (i - 1 - 50); // printf("dpf %d %d %d %I64u %0x\n", j, k, i, midx[j][k][0], midx[j][k][1]); } } } } } int ansv = -1, ansc = 0; unsigned long long idx[2] = {0}; for(int i = 0; i <= b; i++) {//男女匹配,选取最符合题意的组合 if(dpf[female][i] == -1) continue; for(int j = 0; j <= b - i; j++) { if(dpm[male][j] == -1) continue; if(dpf[female][i] + dpm[male][j] > ansv) { ansv = dpf[female][i] + dpm[male][j]; ansc = i + j; idx[0] = fidx[female][i][0] | midx[male][j][0]; idx[1] = fidx[female][i][1] | midx[male][j][1]; } else if(dpf[female][i] + dpm[male][j] == ansv && ansc > i + j) { ansc = i + j; idx[0] = fidx[female][i][0] | midx[male][j][0]; idx[1] = fidx[female][i][1] | midx[male][j][1]; } else if(dpf[female][i] + dpm[male][j] == ansv && ansc == i + j) { int idx0 = fidx[female][i][0] | midx[male][j][0]; int idx1 = fidx[female][i][1] | midx[male][j][1]; if(idx[0] > idx0) { idx[0] = idx0, idx[1] = idx1; } else if(idx[0] == idx[0] && idx[1] > idx1) { idx[0] = idx0, idx[1] = idx1; } } } } printf("%d %d\n", ansv, ansc);// printf("%I64u %0x\n", idx[0], idx[1]); bool flag = false; for(int i = 1; i <= 50; i++) { if(idx[0] & 1) { if(flag) printf(" "); flag = true; printf("%d", i); } idx[0] >>= 1; } for(int i = 51; i <= 100; i++) { if(idx[1] & 1) { if(flag) printf(" "); flag = true; printf("%d", i); } idx[1] >>= 1; } putchar('\n'); }}
- 微软2016校园招聘笔试(第一场) Professor Q's Software & Recruitment
- 微软2016校园招聘在线笔试 - 第二题 Professor Q's Software
- 题目2 : Professor Q's Software【微软2016校园招聘在线笔试】
- hihoCoder 1136 Professor Q's Software 微软2016校园招聘在线笔试
- HiHocoder #1136 : Professor Q's Software 微软2016校园招聘在线笔试 【拓扑排序+DP】
- 微软笔试-Professor Q's Software
- 2016微软实习在线笔试题 - Professor Q's Software
- 微软笔试题 HihoCoder#1136: Professor Q's Software 题解
- 微软线上笔试-2015-4-3(1,2题) Magic Box && Professor Q's Software
- 微软2015实习第二题Professor Q's Software
- 微软2016校园招聘在线笔试第二场
- Lucky Substrings 微软2016校园招聘在线笔试第二场
- Numeric Keypad 微软2016校园招聘在线笔试第二场
- Spring Outing 微软2016校园招聘在线笔试第二场
- 记校园招聘第一场笔试--中兴
- Professor Q's Software Java版本
- hihocoder #1136 : Professor Q's Software
- Professor Q's Software---拓扑排序
- 6.C 总结
- Linux高并发应用类型对系统内核的优化
- @import 与 #import 的区别
- 2015.4.25.13.21_命令行_2015.4.25_java 命令行参数
- 2015德国红点奖获奖作品赏析
- 微软2016校园招聘笔试(第一场) Professor Q's Software & Recruitment
- Python模块导入的多种方式
- 线程池之c语言实现
- sgu 162
- LINUX 使用tcgetattr与tcsetattr函数控制终端
- 如何捕捉返回键
- POSIX信号量解决经典同步问题
- 第八周 阅读程序 (4)
- 对已提供WSDL文件的webservice服务端和客户端的整理