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

牛客网-网易2018校园招聘编程题真题集合-解题思路及源码

2018-01-10 17:30 603 查看
因为牛客网上的题目内容有版权声明,暂时就不复制题目了,需要的同学请自行登录牛客网获取。

1、魔法币

思路:分析题目中发现,魔法机器1只能产生奇数的魔法币,而魔法机器2只能产生偶数的魔法币。本题目采用从结果倒推的思路。比如例子中需要10个魔法币,那么10个魔法币肯定是通过魔法机器2产生,需要给魔法机器2投入4个魔法币才能产生10个。要产生4个魔法币还是要通过魔法机器2,那么需要将1个魔法币投入到魔法机器2种,要产生1个魔法币需要投入0个魔法币到魔法机器1.那么通过倒推后,反向输出就可。

源码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=35;
int main()
{
long long n;
while(cin>>n&&n)
{
int ans[maxn],i=0;
while(n!=0)
{
if(n%2==0)
{
n=(n-2)/2;
ans[i++]=2;
}
else
{
n=(n-1)/2;
ans[i++]=1;
}
}
for(int j=i-1;j>=0;j--)
{
cout<<ans[j];
}
cout<<endl;
}

return 0;
}
2、相反数

思路:输入一个整形的数据后,我们通过取余的方式得到输入数据的个位、十位等以及位数,再反向进行进行计算后相加就行,实际上可能采用字符数组输入更快。

源码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=20;
int main()
{
int n;
while(cin>>n&&n)
{
int i=0,m=n;
int ans[maxn];
while(n)
{
ans[i]=n%10;
n=n/10;
i++;
}
int xfs=0;
for (int j=0;j<i;j++)
xfs +=ans[j]*pow(10,i-j-1);
cout<<xfs+m<<endl;
}
return 0;
}
3、字符串碎片

思路:实际上不需要统计每个碎片的数量,所有碎片的和就为字符串的长度,只需要知道这个字符串被分成了多少个碎片就行。

源码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
string s;
while(getline(cin,s))
{
int np=1;
char p;
p=s[0];
for(int i=0;i<s.length();i++)
{
if(p==s[i])
{}
else
{
np++;
p=s[i];
}
}
printf("%.2f\n",(double)s.length()/np);
}
return 0;
}
4、游历魔法王国

思路:本题目在构建树的时候,是一种特殊构建方法,保证了树中的每一个元素都能够连通。实际上,在构建的过程中,就能够找到从0点出发到叶子节点的最长路径,那么如果步数小于等于最长路径,那么答案就为最长路径,如果步数大于最长路径,可以进行折返,而折返的到达另外一个叶子节点至少需要两步。本题目的测试数据不是很严谨,直接将剩余的步数除以2加上最长路径的步数就可以得到答案。(本题参考了其余网页)

源代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 50 + 5;
int n, L;
int parent[maxn];
int dp[200];
int main() {
scanf("%d%d", &n, &L);
for(int i = 0; i < n - 1; i++) scanf("%d", &parent[i]);
int mx = 0;
for(int i = 0; i < n - 1; i++) {
dp[i + 1] = dp[parent[i]] + 1;
mx = max(mx, dp[i + 1]);
//因为题目给出了一种特殊的树,可以进行这种方式获得最长路径
}
int d = min(L, mx);
cout << min((n), 1 + d + (L - d) / 2)
cac9
<< endl;
return 0;
}
5、重排数列

思路:本题目实际上可以变为在数组中任选两个数相乘能够被4整除。那么首先能够找到满足

(1)被4整除的数乘以任何数都能被4整除;

(2)两个能够被2整除的数相乘就能被4整除。

那么直接统计数字中符合这两种特征数的数量。进行判断就好。

源码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
//freopen("datain.txt","r",stdin);
int t;
cin>>t;
while(t--)
{
int n,d4=0,d2=0,rest=0;
cin>>n;
for(int i=0;i<n;i++)
{
int tmp;
cin>>tmp;
if(tmp%4==0) d4++;
else if(tmp%2==0) d2++;
else rest++;
}
if(d2%2==1)
rest++;
if(rest-1<=d4)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}

return 0;
}
6、最长公共子括号序列

思路:本题咋一看可以通过直接枚举符合要求的括号序列,然后再计算LCS的进行,但是由于字符串的长度可以达到50。这样只能通过测试样例的50%。LCS采用DP实现。

源码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 50+10;
int d[maxn][maxn],ans=0,maxans=0;
string s;
int n;
int  LCS(char *A)
{
d[0][0]=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(A[i]==s[j])
d[i][j]=d[i-1][j-1]+1;
else
d[i][j]=max(d[i-1][j],d[i][j-1]);
}
return d[n-1][n-1];
}
void print_permutation(char * A,int cur)
//n为数组A的长度,A为待排列的数组,cur为A中欲确定元素的位置
{
if(cur==n)//所有元素已经确定完成,输出。
{
int tmp=LCS(A);
if(tmp==maxans)
{
ans++;
}
if(tmp>maxans&&tmp!=n)
{
maxans=tmp;ans=1;
}
}
else
{
//A中的元素没有确定完,尝试在A[cur]填元素
int cntq=0,cnth=0;
for(int j=0;j<cur;j++)
{
if(A[j]=='(') //-1为前括号,如果大于0,。
cntq++;
else
cnth++;
}
if(cntq>cnth&&cntq<(n/2))
{
A[cur]='(';
print_permutation(A,cur+1);
A[cur]=')';
print_permutation(A,cur+1);
}
else if(cntq>cnth&&cntq==(n/2))
{
A[cur]=')';
print_permutation(A,cur+1);
}
else
{
A[cur]='(';
print_permutation(A,cur+1);
}
}

}

int main()
{

char  A[maxn];
cin>>s;
n=s.length();
print_permutation(A,0);
cout<<ans;
return 0;
}
本题目看似很麻烦, 实际上,我们可以得出最长的公共子串的长度为n-1(n输入字符串的长度),那么我们可以在输入的字符串s上,选取s的字符,插入到不同的位置来判断是否满足括号匹配。如果匹配就将它存起来。最后数没有重复的数量就行。举个例子如果输入是s[]="(())()";那么首先将s[1]取出来,将s[1]放在2的位置上,这样就产生一个新的字符串s1。这样s1[0]==s[0],s1[1]==s[2],s1[2]==s1[1]....后面的相等。然后判断s1是否符合括号匹配,如果符合存入map中,这样可以枚举的字符从s[1]到s[n-1],枚举的位置从1到n-1.最后统计map中元素的数量就可以得到答案。

源码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 50+10;
bool judge(char s1[],int n)
{
stack<char> stk1;
for(int i=0;i<n;i++)
{
if(s1[i]=='(')
stk1.push(s1[i]);
else if(!stk1.empty())
stk1.pop();
else
return false;
}
return true;
}
int main()
{
//freopen("datain.txt","r",stdin);
char s[maxn],s1[maxn];
cin>>s;
int ans=-1,n;
n=strlen(s);
s
='\0';
map<string,int> mp1;
mp1[s]=1;
for(int i=1;i<n;i++)
{
for(int j=1;j<n;j++)
{
int nl=0;
s1[nl++]=s[0];
for(int k=1;k<j;k++)
{
if(k!=i)
{
s1[nl++]=s[k];
}

}
s1[nl++]=s[i];
for(int k=j;k<n;k++)
{
if(k!=i)
{
s1[nl++]=s[k];
}

}
s1
='\0';
//cout<<s1<<endl;
if(judge(s1,n))
{
if(!mp1.count(s1))
mp1[s1]=1;
}

}

}
for(map<string,int>::iterator it = mp1.begin(); it!=mp1.end();it++) ans++;
cout<<ans<<endl;
return 0;
}
7、合唱

思路:典型动态规划题,设置状态为d[i][j]为小Q最后一个唱第i个音,牛博士唱第j个音的最小难度。首先设定m=max(i,j)+1;状态转换为:d[i][j]=min(d[m][j]+abs(v[m]-v[i],d[i][m]+abs(v[m]-v[j]));d[i][j]的值依赖后面的值。

源码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2000+10;
int d[maxn][maxn],v[maxn];
int n;
int dp(int i,int j)
{
int m = max(i,j)+1;
if(m>n) return 0;
if(d[i][j]!=-1) return d[i][j];
return d[i][j]=min(dp(m,j)+(i>0?abs(v[m]-v[i]):0),dp(i,m)+(j>0?abs(v[m]-v[j]):0));

}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>v[i];
for(int i=0;i<maxn;i++)
for(int j=0;j<maxn;j++)
d[i][j]=-1;
cout<<dp(0,0)<<endl;

return 0;
}
8、射击游戏

思路:本题目将怪物的旋转转化为旋转坐标轴,枚举角度的方法,可以证明,想要消灭的怪物最多,那么旋转坐标轴后,至少有两点与坐标轴(X轴或Y轴)平行。那么可以通过计算输入坐标,两点连线与x轴的夹角,来获得需要枚举的角度。旋转后,通过平行公式判断与X轴和Y轴平行的怪物的数量,加起来,就为消灭最多怪物的数量。

源码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 50 + 5;
int x[maxn], y[maxn];
int n;
int solve() {
if(n <= 2) return n;
int ans=2;
double x1[maxn],y1[maxn];
//确定枚举的角度
double angles;
for(int i=0;i<n;i++)
for(int j=0;j<i;j++)
{
int cnt=0,vis[maxn];
for(int q=0;q<maxn;q++) vis[q]=1;
angles=atan((double)(y[i]-y[j])/(x[i]-x[j]));
for(int k=0;k<n;k++)
{
x1[k]=x[k]*cos(angles)+y[k]*sin(angles);
y1[k]=y[k]*cos(angles)-x[k]*sin(angles);
}
for(int z=0;z<n;z++)
{
if(fabs(y1[z]-y1[i])<0.001&&vis[z])
{
cnt++;
vis[z]=0;
}

}
int sumpy=0;
for(int z=0;z<n;z++)
{
if(vis[z])
{
vis[z]=0;
int py=1;
for(int p=0;p<n;p++)
if(fabs(x1[z]-x1[p])<0.001&&vis[p])
{
py++;
vis[p]=0;
}
sumpy=max(sumpy,py);
}
}
cnt+=sumpy;
ans=max(ans,cnt);
}
//根据枚举的角度进行旋转
return ans;
}
int main() {
//freopen("datain.txt","r",stdin);
cin >> n;
for(int i = 0; i < n; i++) cin >> x[i];
for(int i = 0; i < n; i++) cin >> y[i];
cout << solve() << endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: