牛客网真题练习-
网易2017春招笔试真题编程题集合
双核处理
一种双核CPU的两个核能够同时的处理任务,现在有n个已知数据量的任务需要交给CPU处理,假设已知CPU的每个核1秒可以处理1kb,每个核同时只能处理一项任务。n个任务可以按照任意顺序放入CPU进行处理,现在需要设计一个方案让CPU处理完这批任务所需的时间最少,求这个最小的时间。
输入描述:
输入包括两行: 第一行为整数n(1 ≤ n ≤ 50) 第二行为n个整数length[i](1024 ≤ length[i] ≤ 4194304),表示每个任务的长度为length[i]kb,每个数均为1024的倍数。
输出描述:
输出一个整数,表示最少需要处理的时间
输入例子
5 3072 3072 7168 3072 1024
输出例子:
9216
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
const int MAXN = 55;
const int MAXM = 800000;
int n,sum, num[MAXN], dp[MAXM];
int main(){
freopen("in.txt", "r", stdin);
int tmp, ans;
scanf("%d", &n);
sum = 0;
for(int i=0; i<n; ++i){
scanf("%d", &num[i]);
sum += num[i];
}
memset(dp, 0, sizeof(dp));
dp[0] = 1;
for(int i=0; i<n; ++i){
tmp = num[i]/1024;
for(int j=sum/1024; j>=tmp; --j){
if(dp[j - tmp] == 1){
dp[j] = 1;
}
}
}
ans = 0;
tmp = sum/(2*1024);
for(int i=0; i<sum/1024; ++i){
if(dp[tmp-i] == 1){
ans = 1024*(tmp-i);
break;
}
if(dp[tmp+i] == 1){
ans = 1024*(tmp+i);
break;
}
}
ans = max(sum-ans, ans);
printf("%d\n", ans );
return 0;
}
赶去公司
终于到周末啦!小易走在市区的街道上准备找朋友聚会,突然服务器发来警报,小易需要立即回公司修复这个紧急bug。假设市区是一个无限大的区域,每条街道假设坐标是(X,Y),小易当前在(0,0)街道,办公室在(gx,gy)街道上。小易周围有多个出租车打车点,小易赶去办公室有两种选择,一种就是走路去公司,另外一种就是走到一个出租车打车点,然后从打车点的位置坐出租车去公司。每次移动到相邻的街道(横向或者纵向)走路将会花费walkTime时间,打车将花费taxiTime时间。小易需要尽快赶到公司去,现在小易想知道他最快需要花费多少时间去公司。
输入描述:
输入数据包括五行:
第一行为周围出租车打车点的个数n(1 ≤ n ≤ 50)
第二行为每个出租车打车点的横坐标tX[i] (-10000 ≤ tX[i] ≤ 10000)
第三行为每个出租车打车点的纵坐标tY[i] (-10000 ≤ tY[i] ≤ 10000)
第四行为办公室坐标gx,gy(-10000 ≤ gx,gy ≤ 10000),以空格分隔
第五行为走路时间walkTime(1 ≤ walkTime ≤ 1000)和taxiTime(1 ≤ taxiTime ≤ 1000),以空格分隔
输出描述:
输出一个整数表示,小易最快能赶到办公室的时间
输入例子:
2 -2 -2 0 -2 -4 -2 15 3
输出例子:
42
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
using namespace std;
const int MAXN = 50;
int X[MAXN], Y[MAXN];
int main(){
freopen("in.txt", "r", stdin);
int ans, gx, gy, Wt, Tt, n, tmp;
scanf("%d", &n);
for(int i=0; i<n; ++i){
scanf("%d", &X[i]);
}
for(int i=0; i<n; ++i){
scanf("%d", &Y[i]);
}
scanf("%d%d", &gx, &gy);
scanf("%d%d", &Wt, &Tt);
ans = (abs(gx) + abs(gy))*Wt;
for(int i=0; i<n; ++i){
tmp = (abs(X[i]) + abs(Y[i]))*Wt + (abs(gx - X[i]) + abs(gy - Y[i]))*Tt;
if(tmp < ans){
ans = tmp;
}
}
printf("%d\n", ans );
return 0;
}
消除重复元素
小易有一个长度为n序列,小易想移除掉里面的重复元素,但是小易想是对于每种元素保留最后出现的那个。小易遇到了困难,希望你来帮助他。
输入描述:
输入包括两行: 第一行为序列长度n(1 ≤ n ≤ 50) 第二行为n个数sequence[i](1 ≤ sequence[i] ≤ 1000),以空格分隔
输出描述:
输出消除重复元素之后的序列,以空格分隔,行末无空格
输入例子:
9 100 100 100 99 99 99 100 100 100
输出例子:
99 100
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <map>
#include <vector>
using namespace std;
const int MAXN = 55;
int main(){
freopen("in.txt", "r", stdin);
int n, num[MAXN];
scanf("%d", &n);
for(int i=0; i<n; ++i){
scanf("%d", &num[i]);
}
vector<int> ans;
map<int, int> mp;
for(int i=n-1; i>=0; --i){
if( mp.find( num[i] ) == mp.end()){
mp[ num[i] ] = 1;
ans.push_back( num[i] );
}
}
for(int i=ans.size()-1;i>=0; --i){
if(i==0){
printf("%d\n", ans[i] );
}else{
printf("%d ", ans[i] );
}
}
return 0;
}
工作安排
现在有n位工程师和6项工作(编号为0至5),现在给出每个人能够胜任的工作序号表(用一个字符串表示,比如:045,表示某位工程师能够胜任0号,4号,5号工作)。现在需要进行工作安排,每位工程师只能被安排到自己能够胜任的工作当中去,两位工程师不能安排到同一项工作当中去。如果两种工作安排中有一个人被安排在的工作序号不一样就被视为不同的工作安排,现在需要计算出有多少种不同工作安排计划。
输入描述:
输入数据有n+1行: 第一行为工程师人数n(1 ≤ n ≤ 6) 接下来的n行,每行一个字符串表示第i(1 ≤ i ≤ n)个人能够胜任的工作(字符串不一定等长的)
输出描述:
输出一个整数,表示有多少种不同的工作安排方案
输入例子:
6 012345 012345 012345 012345 012345 012345
输出例子:
720
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
const int MAXN = 10;
int n, ans, var[MAXN][MAXN], vis[MAXN];
void dfs(int cur){
if(cur == n){
ans++;
return;
}
for(int i=0; i<=5; ++i){
if(vis[i] == 0 && var[cur][i] == 1){
vis[i] = 1;
dfs(cur+1);
vis[i] = 0;
}
}
}
int main(){
freopen("in.txt", "r", stdin);
char st[MAXN];
scanf("%d", &n);
memset(var, 0, sizeof(var));
for(int i=0; i<n; ++i){
scanf("%s", st);
for(int j=0; j<strlen(st); ++j){
var[i][st[j]-'0'] = 1;
}
}
ans = 0;
memset(vis, 0, sizeof(vis));
dfs(0);
printf("%d\n", ans );
return 0;
}
奇怪的表达式求值
常规的表达式求值,我们都会根据计算的优先级来计算。比如*/的优先级就高于+-。但是小易所生活的世界的表达式规则很简单,从左往右依次计算即可,而且小易所在的世界没有除法,意味着表达式中没有/,只有(+, - 和 *)。现在给出一个表达式,需要你帮忙计算出小易所在的世界这个表达式的值为多少
输入描述:
输入为一行字符串,即一个表达式。其中运算符只有-,+,*。参与计算的数字只有0~9. 保证表达式都是合法的,排列规则如样例所示。
输出描述
输出一个数,即表达式的值
输入例子:
3+5*7
输出例子:
56
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
const int MAXN = 100;
int main(){
char st[MAXN];
int flag, ans, tmp, len, i;
while(scanf("%s", st) != EOF){
ans = 0; len = strlen(st);
tmp = 0; i = 0; flag = 1;
while(i < len){
if(st[i] == '+'){
flag = 1;
}else if(st[i] == '-'){
flag = 2;
}else if(st[i] == '*'){
flag = 3;
}else{
tmp = st[i] - '0';
while(i < len && st[i+1]>='0' && st[i+1]<='9'){
i++;
tmp = tmp*10 + st[i]-'0';
}
if(flag==1){
ans += tmp;
}else if(flag==2){
ans -= tmp;
}else{
ans *= tmp;
}
}
i++;
}
printf("%d", ans);
}
return 0;
}
涂棋盘
小易有一块n*n的棋盘,棋盘的每一个格子都为黑色或者白色,小易现在要用他喜欢的红色去涂画棋盘。小易会找出棋盘中某一列中拥有相同颜色的最大的区域去涂画,帮助小易算算他会涂画多少个棋格。
输入描述:
输入数据包括n+1行:
第一行为一个整数n(1 ≤ n ≤ 50),即棋盘的大小
接下来的n行每行一个字符串表示第i行棋盘的颜色,'W'表示白色,'B'表示黑色
输出描述:
输出小易会涂画的区域大小
输入例子:
3 BWW BBB BWB
输出例子:
3
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 55;
int n, ans, tmp, mp[MAXN][MAXN];
void dfs(int cx, int cy, int label){
tmp++;
mp[cx][cy] = 0;
if(cx+1<n && mp[cx+1][cy] == label){
dfs(cx+1, cy, label);
}
}
int main(){
char ch;
scanf("%d", &n);
for(int i=0; i<n; ++i){
getchar();
for(int j=0; j<n; ++j){
scanf("%c", &ch);
if(ch == 'B'){
mp[i][j] = -1;
}else{
mp[i][j] = 1;
}
}
}
ans = 0;
for(int i=0; i<n; ++i){
for(int j=0; j<n; ++j){
if(mp[i][j] != 0){
tmp = 0;
dfs(i, j, mp[i][j]);
if(tmp > ans){
ans = tmp;
}
}
}
}
printf("%d", ans);
return 0;
}
集合
小易最近在数学课上学习到了集合的概念,集合有三个特征:1.确定性 2.互异性 3.无序性.
小易的老师给了小易这样一个集合:
S = { p/q | w ≤ p ≤ x, y ≤ q ≤ z }
需要根据给定的w,x,y,z,求出集合中一共有多少个元素。小易才学习了集合还解决不了这个复杂的问题,需要你来帮助他。
输入描述:
输入包括一行: 一共4个整数分别是w(1 ≤ w ≤ x),x(1 ≤ x ≤ 100),y(1 ≤ y ≤ z),z(1 ≤ z ≤ 100).以空格分隔
输出描述:
输出集合中元素的个数
输入例:
1 10 1 1
输出例子:
10
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
int GCD(int x, int y){
if(x == 0){
return y;
}
return GCD(y%x, x);
}
int main(){
int w, x, y, z, tv;
cin >> w >> x >> y >> z;
set< pair<int,int> > st;
for(int i=w; i<=x; ++i){
for(int j=y; j<=z; ++j){
tv = GCD(min(i,j), max(i,j));
st.insert( make_pair(i/tv, j/tv) );
}
}
cout << st.size() << endl;
return 0;
}
小易记单词
小易参与了一个记单词的小游戏。游戏开始系统提供了m个不同的单词,小易记忆一段时间之后需要在纸上写出他记住的单词。小易一共写出了n个他能记住的单词,如果小易写出的单词是在系统提供的,将获得这个单词长度的平方的分数。注意小易写出的单词可能重复,但是对于每个正确的单词只能计分一次。
输入描述:
输入数据包括三行:
第一行为两个整数n(1 ≤ n ≤ 50)和m(1 ≤ m ≤ 50)。以空格分隔
第二行为n个字符串,表示小易能记住的单词,以空格分隔,每个单词的长度小于等于50。
第三行为m个字符串,系统提供的单词,以空格分隔,每个单词的长度小于等于50。
输出描述:
输出一个整数表示小易能获得的分数
输入例子:
3 4 apple orange strawberry strawberry orange grapefruit watermelon
输出例子:
136
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main(){
int n, m, ans = 0;
string st;
cin >> n >> m;
map<string, int> mp;
for(int i=0; i<n; ++i){
cin >> st;
mp[st] = 1;
}
for(int i=0; i<m; ++i){
cin >> st;
if(mp.find(st) == mp.end()){
continue;
}else{
if(mp[st] == 1){
ans += st.length() * st.length();
mp[st] = 2;
}
}
}
cout << ans << endl;
return 0;
}
调整队形
在幼儿园有n个小朋友排列为一个队伍,从左到右一个挨着一个编号为(0~n-1)。其中有一些是男生,有一些是女生,男生用'B'表示,女生用'G'表示。小朋友们都很顽皮,当一个男生挨着的是女生的时候就会发生矛盾。作为幼儿园的老师,你需要让男生挨着女生或者女生挨着男生的情况最少。你只能在原队形上进行调整,每次调整只能让相邻的两个小朋友交换位置,现在需要尽快完成队伍调整,你需要计算出最少需要调整多少次可以让上述情况最少。例如:
GGBBG -> GGBGB -> GGGBB
这样就使之前的两处男女相邻变为一处相邻,需要调整队形2次
输入描述:
输入数据包括一个长度为n且只包含G和B的字符串.n不超过50.
输出描述:
输出一个整数,表示最少需要的调整队伍的次数
输入例子:
GGBBG
输出例子:
2
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
const int MAXN = 100;
int main(){
int len, bb, gg, lb, rb, ans;
char ch[MAXN];
while(scanf("%s", ch) != EOF){
len = strlen(ch);
bb = 0; gg = 0; lb = 0; rb = 0;
for(int i=0; i<len; ++i){
if(ch[i] == 'B'){
lb += i - bb; bb++;
}else{
rb += i - gg; gg++;
}
}
ans = lb>rb?rb:lb;
printf("%d\n", ans );
}
return 0;
}