牛客网-网易2018校园招聘编程题真题集合-解题思路及源码
2018-01-10 17:30
603 查看
因为牛客网上的题目内容有版权声明,暂时就不复制题目了,需要的同学请自行登录牛客网获取。
1、魔法币
思路:分析题目中发现,魔法机器1只能产生奇数的魔法币,而魔法机器2只能产生偶数的魔法币。本题目采用从结果倒推的思路。比如例子中需要10个魔法币,那么10个魔法币肯定是通过魔法机器2产生,需要给魔法机器2投入4个魔法币才能产生10个。要产生4个魔法币还是要通过魔法机器2,那么需要将1个魔法币投入到魔法机器2种,要产生1个魔法币需要投入0个魔法币到魔法机器1.那么通过倒推后,反向输出就可。
源码:
思路:输入一个整形的数据后,我们通过取余的方式得到输入数据的个位、十位等以及位数,再反向进行进行计算后相加就行,实际上可能采用字符数组输入更快。
源码:
思路:实际上不需要统计每个碎片的数量,所有碎片的和就为字符串的长度,只需要知道这个字符串被分成了多少个碎片就行。
源码:
思路:本题目在构建树的时候,是一种特殊构建方法,保证了树中的每一个元素都能够连通。实际上,在构建的过程中,就能够找到从0点出发到叶子节点的最长路径,那么如果步数小于等于最长路径,那么答案就为最长路径,如果步数大于最长路径,可以进行折返,而折返的到达另外一个叶子节点至少需要两步。本题目的测试数据不是很严谨,直接将剩余的步数除以2加上最长路径的步数就可以得到答案。(本题参考了其余网页)
源代码:
思路:本题目实际上可以变为在数组中任选两个数相乘能够被4整除。那么首先能够找到满足
(1)被4整除的数乘以任何数都能被4整除;
(2)两个能够被2整除的数相乘就能被4整除。
那么直接统计数字中符合这两种特征数的数量。进行判断就好。
源码:
思路:本题咋一看可以通过直接枚举符合要求的括号序列,然后再计算LCS的进行,但是由于字符串的长度可以达到50。这样只能通过测试样例的50%。LCS采用DP实现。
源码:
源码:
思路:典型动态规划题,设置状态为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]的值依赖后面的值。
源码:
思路:本题目将怪物的旋转转化为旋转坐标轴,枚举角度的方法,可以证明,想要消灭的怪物最多,那么旋转坐标轴后,至少有两点与坐标轴(X轴或Y轴)平行。那么可以通过计算输入坐标,两点连线与x轴的夹角,来获得需要枚举的角度。旋转后,通过平行公式判断与X轴和Y轴平行的怪物的数量,加起来,就为消灭最多怪物的数量。
源码:
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; }
相关文章推荐
- 牛客网-网易2017春招笔试真题编程题集合-解题思路及源码
- [网易]2018校园招聘编程题真题集合
- 牛客网-2017网易游戏雷火盘古实习生招聘笔试真题-解题思路及源码
- 网易2018校园招聘编程题真题集合之重排序列
- 网易2018校园招聘编程题真题集合1魔法币
- 网易2018校园招聘编程题真题集合
- 网易2018校园招聘编程题真题集合(一)
- 网易2018校园招聘编程题真题集合2相反数
- [网易]2018校园招聘编程题真题集合
- 网易2018校园招聘编程题真题集合
- 网易2018校园招聘编程题真题集合3字符串碎片
- 网易2018校园招聘编程题真题集合 (部分)
- 牛客网-网易2018校招内推编程题集合-解题思路及源码
- 网易2018校园招聘编程题真题-[编程题] 魔法币
- 网易2018校园招聘编程题真题 合唱
- 牛客网-网易2017秋招编程题集合-解题思路及源码
- 网易2018校园招聘编程题真题-[编程题] 字符串碎片
- 网易2018校园招聘编程题真题-[编程题] 交错01串
- 网易2018校园招聘编程题真题-[编程题] 相反数
- 网易2018校园招聘编程题