您的位置:首页 > 编程语言

牛客网-网易2017春招笔试真题编程题集合-解题思路及源码

2018-01-26 17:34 609 查看
一、双核处理

本题目是0-1背包的变种,题目的目标是求最少需要处理的时间。可以将目标转化为在 总任务长度/2的时间内,一个CPU最多能处理的任务量,那么答案为 总任务量-在总任务长度/2的时间内最多工作量。 因为工作时间的理想最小值为总任务长度/2,那么如果一个cpu的处理时间大于总任务长度/2,那么另外一个CPU就必然小于总任务长度/2。目标实际上就转化为处理少的那个CPU尽量逼近理想值。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 55;
const int maxh=4096*26;
int d[2][maxh];
int main()
{
int n,a[maxn],sum=0;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i]/=1024;
sum+=a[i];
}

for(int i=n;i>0;i--)
for(int j=0;j<=sum/2;j++)
{
d[i&1][j]=(i==n?0:d[(i+1)&1][j]);
if(j>=a[i])
d[i&1][j]=max(d[i&1][j],d[(i+1)&1][j-a[i]]+a[i]);
}
int ans = max (d[1][sum/2],sum-d[1][sum/2]);
cout<<ans*1024<<endl;
return 0;
}
二、赶去公司

本题目直接枚举出各种情况下的值,就可以得到答案。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn=10000+100;
int computedis(int x1,int y1,int x2,int y2)
{
return abs(x1-x2)+abs(y1-y2);
}
int main()
{
int n,tx[maxn],ty[maxn],gx,gy,walktime,taxitime,ans;
cin>>n;
for(int i=0;i<n;i++) cin>>tx[i];
for(int i=0;i<n;i++) cin>>ty[i];
cin>>gx>>gy;
cin>>walktime>>taxitime;
ans=computedis(0,0,gx,gy)*walktime;
for(int i=0;i<n;i++)
{
int tmp =computedis(0,0,tx[i],ty[i])*walktime+computedis(tx[i],ty[i],gx,gy)*taxitime;
if(ans>tmp)
ans=tmp;
}
cout<<ans<<endl;

return 0;
}

三、调整队形

本题目可以设想两种情况一种为G开通,一种为B开头。比如GGBGG,需要移动后面两个到前面,实际上一个G的移动次数等于G中间B的个数,上面例子中有2个G要移动B的个数为1,那么2*1=2.只需要两次就能调整完。

代码如下:

#include<bits/stdc++.h>
using namespace std;
int main()
{
//freopen("datain.txt","r",stdin);
string s;
cin>>s;
char start;
start = s[0];
int cnt=0,ans=0,ans2=0;
int i=1;
while(start==s[i]) i++;
for(;i<s.length();i++)
{

if(start!=s[i])
cnt++;
else
ans+=cnt;
}
cnt=0;
start = s[0];
i=1;
while(start==s[i])
{
i++;
}
start=s[i];
cnt=i;ans2+=cnt;
i++;
for(;i<s.length();i++)
{

if(start!=s[i])
cnt++;
else
ans2+=cnt;
}
if(ans2>ans)
cout<<ans<<endl;
else
cout<<ans2<<endl;
return 0;
}
四、消除重复元素

本题可以构建一个结构体存储数字的值和位置,通过值来判断重复,通过位置来帮助输出。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000+10;
struct num
{
int value;
int pos;
bool operator < (const num n1) const{
return  pos< n1.pos;
}
};

int main()
{
int n,len=0;
num num1[maxn];
cin>>n;
for(int i=0;i<n;i++)
{
int x,flag=1;
cin>>x;
for(int j=0;j<len;j++)
{
if(num1[j].value==x)
{
flag=0;
num1[j].pos=i;
break;
}

}
if(flag)
{
num1[len].value=x;
num1[len].pos=i;
len++;
}

}
sort(num1,num1+len);
for(int i=0;i<len-1;i++)
{
cout<<num1[i].value<<" ";
}
cout<<num1[len-1].value<<endl;
return 0;
}
五、魔力手环

本题目因为计算量太大,不能直接枚举。采用快速幂矩阵的方式,进行状态的快速变换。具体可以参考点击打开链接,通过将每次状态变化,转换成矩阵的乘法,通过矩阵运算来降低算法的复杂度。

代码如下:

#include<bits/stdc++.h>
using namespace std;
//构建快速幂矩阵
const int maxn=50+10;
int ans[maxn];
int anspre[maxn];
int fast[maxn][maxn];
int fastpre[maxn][maxn];
int n,k;
int compute(int i,int j,int fast[maxn][maxn])
{
int sum=0;
for(int k=0;k<n;k++)
sum=(sum+(fast[i][k]*fast[k][j]))%100;
return sum;
}
int main()
{
//freopen("datain.txt","r",stdin);
cin>>n>>k;
for(int i=0;i<n;i++)
{
cin>>ans[i];
}
for(int i=0;i<n-1;i++)
{
fast[i][i]=1;
fast[i+1][i]=1;
}
fast[n-1][n-1]=1;
fast[0][n-1]=1;
//快速幂矩阵求解
while(k)
{
for(int i=0;i<n;i++)
{
memcpy(fastpre[i],fast[i],sizeof(fastpre[i]));
}
memcpy(anspre,ans,sizeof(anspre));
if(k&1)
{

for(int i=0;i<n;i++)
{
int tmp=0;
for(int j=0;j<n;j++)
{
tmp=(tmp+anspre[j]*fast[j][i])%100;
}
ans[i]=tmp;
}
}
k=k>>1;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
fast[i][j]=compute(i,j,fastpre);

}
for (int i=0;i<n-1;i++)
cout<<ans[i]<<" ";
cout<<ans[n-1]<<endl;
return 0;
}
六、工作安排

因为工作只有6种,那么直接枚举可能就行。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 10;
int n,work[maxn][maxn],ans=0;
bool judge(int *A)
{
int flag=true;
for(int i=0;i<n;i++)
if(work[i][A[i]]==0)
{
flag=false;
break;
}
return flag;
}
void permutation(int n,int* A,int cur)
{
if(cur==n)//所有元素已经确定完成,输出。
{
if(judge(A))
ans++;
}
else for(int i=0;i<6;i++)
//A中的元素没有确定完,尝试在A[cur]填元素
{
int ok=1;
for(int j=0;j<cur;j++)
{
if(A[j]==i)
ok=0;
}
if(ok)
{
A[cur]=i;
permutation(n,A,cur+1);
}
}
}
int main()
{
//freopen("datain.txt","r",stdin);
for(int i=0;i<maxn;i++)
for(int j=0;j<maxn;j++)
work[i][j]=0;
cin>>n;
for(int i=0;i<n;i++)
{
string s;
cin>>s;
for(int j=0;j<s.length();j++)
{
work[i][s[j]-'0']=1;
}
}
int A[maxn];
permutation(n,A,0);
cout<<ans<<endl;
return 0;
}
七、集合

本题也是采取暴力方式求解,使用map存储已经获得的元素,避免重复输出。

#include<bits/stdc++.h>
using namespace std;
int main()
{
map<double,int> mp1;
int w,x,y,z,ans=0;
cin>>w>>x>>y>>z;
for(int i=w;i<=x;i++)
for(int j=y;j<=z;j++)
{
double tmp=(double)i/j;
if(!mp1.count(tmp))
{
ans++;
mp1[tmp]=1;
}
}
cout<<ans<<endl;
return 0;
}
八、奇怪的表达式求值

本题目采用1个双端队列存储操作数,1个队列存储操作符,就能满足题目要求。

代码如下:

#include<bits/stdc++.h>
using namespace std;
int main()
{
deque<int> dq1;
deque<char> dq2;
string s;
cin>>s;
for(int i=0;i<s.length()-1;i=i+2)
{
dq1.push_back(s[i]-'0');
dq2.push_back(s[i+1]);
}
dq1.push_back(s[s.length()-1]-'0');
int  num1,num2,num3;
char ope;
while(!dq2.empty())
{
ope=dq2.front();
dq2.pop_front();
num1=dq1.front();
dq1.pop_front();
num2=dq1.front();
dq1.pop_front();
if(ope=='+')
num3=num1+
bbae
num2;
else if(ope=='-')
num3=num1-num2;
else if(ope=='*')
num3=num1*num2;
dq1.push_front(num3);
}
cout<<dq1.front()<<endl;

return 0;
}
九、涂棋盘

根据题目数格子就行。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 50+10;
int main()
{
int n;
char G[maxn][maxn];
cin>>n;
for(int i=0;i<n;i++)
{
string s;
cin>>s;
for (int j=0;j<n;j++)
{
G[i][j]=s[j];
}
}
int maxBW=0;
for(int i=0;i<n;i++)
{
int len=0;
char c = G[0][i];
for(int j=0;j<n;j++)
{

if(G[j][i]==c)
len++;
else
{
if(maxBW<len)
maxBW=len;
len=1;
c=G[j][i];
}
}
if(maxBW<len)
maxBW=len;
}

cout<<maxBW<<endl;

}

十、小易记单词

本题目使用map来存储准确答案,当输入的答案存在map中的时候,得分。否则不得分。

#include<bits/stdc++.h>
using namespace std;
const int maxn=60;
int main()
{
//freopen("datain.txt","r",stdin);
map<string,int> mp;
string ans[maxn];
int n,m,res=0;
cin>>n>>m;
for(int i=0;i<n;i++)
{
cin>>ans[i];
}
for(int i=0;i<m;i++)
{
string s;
cin>>s;
mp[s]=1;
}
for(int i=0;i<n;i++)
{
if(mp[ans[i]]==1)
{
res=res+ans[i].length()*ans[i].length();
mp[ans[i]]++;
}

}
cout<<res<<endl;

return 0;
}
十一、堆砖块

本题目使用动态规划,需要将优化目标进行转换,具体可以参考点击打开链接,采用动态规划的时候,可能出现空间不够的情况,参考链接中的方法直接使用 &1 的方式,也就是滚动数组的方式,值得学习。另外一种是采用枚举+剪枝。这个方法也理解比动态规划简单。

十二、分饼干
本题目,直接枚举只有50%的通过率。因为取余运算可以这样表示 1120%7=(1000%7+100%7+20%7+0%7)%7,那么采用d[i][j]表示在前i位后,余数为j的数量。当位数不为X的时候,数量不会增加,但是会转移,比如前2为时候余数1的数量为1,第3位不为X的话,那么余数1的那个数量1可能会转移到余数2等等。当为X的时候,数量会转移也会增加。

#include<bits/stdc++.h>
using namespace std;
const int maxn=20;
const int maxm=100000;
long long d[maxn][maxm];
int main()
{
//freopen("datain.txt","r",stdin);
long long n;
string s;
cin>>s;
cin>>n;
int tmp1=(long long)((s[0]-'0')*pow(10,s.length()-1))%n;
d[1][tmp1]=1;
for(int i=1;i<s.length();i++)
{
if(s[i]!='X')
{
int tmp=(long long)((s[i]-'0')*pow(10,s.length()-1-i))%n;
for(int j=0;j<n;j++)
{
d[i+1][(tmp+j)%n]=d[i][j];
}
}
else
{
for(int j=0;j<10;j++)
{
int tmp=(long long )(j*pow(10,s.length()-1-i))%n;
for(int k=0;k<n;k++)
{
d[i+1][(tmp+k)%n]=d[i][k]+d[i+1][(tmp+k)%n];
}

}
}

}
cout<<d[s.length()][0]<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: