牛客网-网易2018校招内推编程题集合-解题思路及源码

本文解析了八道编程挑战题的解决思路及代码实现,包括彩色砖块计数、等差数列验证、交错01串寻找、操作序列重构、独立小易问题求解、堆棋子布局优化、疯狂队列安排与小易数列构造。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、彩色的砖块

思路:本题实际上是统计不同颜色砖块的数量,根据数量的不同进行输出就行。

源码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=100;
int main()
{
	string s;
	cin>>s;
	stringstream ss(s);
	int a[maxn];
	int sum=0;
	for (int i=0;i<maxn;i++) a[i]=0;
	while(ss)
	{
		char tmp;
		ss>>tmp;
		a[tmp-'A']++;
	}
	for(int i=0;i<maxn;i++)
	{
		if(a[i]!=0)
			sum++;
	}
	if(sum==1)
		cout<<'1'<<endl;
	if(sum==2)
		cout<<'2'<<endl;
	if(sum>=3)
		cout<<'0'<<endl;
	return 0;
} 
2、等差数列

思路:本题目先排序,然后再根据等差数列的条件进行判断可以得到答案。

源码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=100;
int main()
{
	int n,flag=1;
	cin>>n;
	int s[maxn];
	for (int i=0;i<n;i++) cin>>s[i];
	sort(s,s+n);
	int d = s[1]-s[0];
	for(int i=0;i<n-1;i++)
	{
		if(s[i]+d!=s[i+1])
		{
			flag=0;
			break;
		}
	}
	if(flag) cout<<"Possible"<<endl;
	else cout<<"Impossible"<<endl;
	return 0;
}
3、交错01串

思路:枚举起点,然后得到符合要求串的长度,选择最长的子串即可。

源码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=100;
int main()
{
	int begin,end;
	int lenth=0;
	string s;
	cin>>s;
	for(int i=0;i<s.length();i++)
	{
		begin = i;
		end = i;
		while(!(s[end]-'0')==(s[end+1]-'0'))
			end++;
		if(end-begin+1>lenth)
		{
			lenth=end-begin+1;
		}
	}
	cout<<lenth;
		
	return 0;
}
4、操作序列

思路:本题可以将两步操作当成一步看,从结果中找出规律。实际上,因为第一步为加入到序列的末尾,然后进行逆序。可以得到这次加入的整数实际的位置在第一个。而上一次加入整数实际的位置被变化到最后一个。

源码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=200000+1000;
int main()
{
	int  a[maxn],b[maxn];
	int an,begin=0;
	cin>>an;
	int end=an-1;
	for(int i=0;i<an;i++) cin>>a[i];
	for(int i=an-1;i>=0;i-=2)
	{
		b[begin++]=a[i];
		if(end>begin-1)
		b[end--]=a[i-1];
		
	}
	for(int i=0;i<an-1;i++) cout<<b[i]<<" ";
	cout<<b[an-1]<<endl;
	return 0;
}

5、独立的小易

思路:本题是一个线性规划问题,但是要注意 天数-f 可能出现负数,要进行区别的处理。另外寻找答案的时候,直接穷举要超时,可以通过二分查找。

源码:

#include<bits/stdc++.h>
using namespace std;
const long long  maxn=2000000000;
int main()
{
	long long  x,f,d,p;
	cin>>x>>f>>d>>p;
	long long  low=0,high=maxn; 
	long long  mid=0;
    while(low<=high)
        {
			mid=(low+high)/2;
            if(mid-f>=0)
			{	
				if(x*mid+(mid-f)*p<=d) low=mid+1;
				else high=mid-1;	
		    }
			else
			{
				if(x*mid<=d) low=mid+1;	
				else high=mid-1;
			} 
			
        }
        mid=(low+high)/2;
	cout<<mid<<endl;
	return 0;
}
6、堆棋子

思路:本题可以推导出最后各个棋子要移动的终点,X的范围就是在输入的X坐标中选择,Y的范围就是在输入的Y坐标中选择。具体证明推导可以百度本题得到。这样就可以枚举终点。然后进行计算每个棋子到达终点的步数、排序、就可以记录下所有终点,1个棋子到n个棋子的步数,然后再选择其中最少的步数输出。

源码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=50+10;
const int INF=0x3f3f3f3f;
int n,x[maxn],y[maxn],ans[maxn*maxn][maxn],anstmp[maxn],res=INF,res1[maxn];

int main()
{
	//freopen("datain1.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];	
	for(int i=0;i<maxn*maxn;i++)
		for(int j=0;j<maxn;j++)
			ans[i][j]=0;
	int len=0;
	for(int i=0;i<n;i++)//枚举终点 
	{
		for(int j=0;j<n;j++)
		{
			int sx=x[i],sy=y[j];
			for(int k=0;k<n;k++)
			anstmp[k]=abs(x[k]-sx)+abs(y[k]-sy);
			sort(anstmp,anstmp+n); 
			for(int m=1;m<=n;m++)
			{
				for(int r=0;r<m;r++)
					ans[len][m]=ans[len][m]+anstmp[r];
			}
			len++;
		}
	
	}
	for(int m=1;m<=n;m++)
	{
		res=INF;
		for(int r=0;r<len;r++)
			res=min(res,ans[r][m]);
		res1[m]=res;
	}
	for(int i=1;i<n;i++) cout<<res1[i]<<" ";
	cout<<res1[n]<<endl;
	return 0;
} 
7、疯狂队列

思路:本题采用贪婪的思想,第一次先排最大身高和最小身高肯定是排在一起的。第二次是次小身高的和最大身高排在一起,次大的和最小身高排在一起。循环反复。但是要注意的是,当执行完还剩下最后一个数的时候,这个数需要和已经排好的队头和队尾比较,然后再排进去。

源码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000+100;
int main()
{
	
	int h[maxn],maxh[maxn];
	for(int i=0;i<maxn;i++) maxh[i]=0;
	int n,sum=0;
	cin>>n;
	for(int i=0;i<n;i++) cin>>h[i];
	sort(h,h+n);
	int pre=maxn/2,pos=maxn/2+1;
	maxh[pre--]=h[n-1];
	maxh[pos++]=h[0];
	int cnt=0;
	for(int i=1;i<=(n-1)/2;i++)
	{
		if(cnt%2==0)
		{
			if(n-1-i>i)
			{
				maxh[pre]=h[i];
				pre--;
				maxh[pos]=h[n-1-i];
				pos++; 
			}
			if(n-1-i==i)
			{
				if(abs(h[i]-maxh[pre+1])>abs(h[i]-maxh[pos-1]))
					{maxh[pre]=h[i];pre++;}
				else
				{maxh[pos]=h[i];pos++;}
			}	
		}
		else 
		{	
			if(n-1-i>i)
			{
				maxh[pos]=h[i];
				pos++;
				maxh[pre]=h[n-1-i];
				pre--; 
			}
			if(n-1-i==i)
			{
				if(abs(h[i]-maxh[pre+1])>abs(h[i]-maxh[pos-1]))
					{maxh[pre]=h[i];pre++;}
				else
				{maxh[pos]=h[i];pos++;}
			}
			
		}
		cnt++;	
	}
	pre=0;
	while(!maxh[pre]) pre++;
	for(int i=pre;i<pre+n-1;i++)
		sum+=abs(maxh[i+1]-maxh[i]);
	cout<<sum<<endl;
	return 0;
}
8、小易喜欢的数列

思路:本题如果直接采用枚举的方法和普通的动态规划求解都只能通过40%的数据。

源码:

//参考链接:http://blog.youkuaiyun.com/shiwaigaoren12345/article/details/77248319
//本程序分层计算,在每一层通过排除不符合要求的数列,来计算得到本层符合要求数列的数量。
//其中状态dp[i][j]表示长度为i,以j结尾符合要求数量的数量
#include <iostream>  
# define f(i,m,n) for(int i=m; i<=n; i++)  
using namespace std;  
const int mod=1000000007;  
int dp[15][100010], last, now, n, k;  
int main(){  
    cin>>n>>k;  
    last=0;  
    f(i, 1, k){  
        dp[1][i]=1;  
        last=(last+dp[1][i]%mod)%mod;
		
    } 
	//计算d[i][j]的方式是通过排除 
    f(i, 2, n){//从长度为2开始计算  
        now=0; // now帮助last记录了在某个长度下,所有符合要求数列的数量 
        f(j, 1, k){ //从数1结尾开始枚举 
            int sum=0;  
            for(int t=2*j; t<=k; t=t+j)  
            sum=(sum+dp[i-1][t])%mod;  
            dp[i][j]=(last-sum+mod)%mod;  
            now=(now+dp[i][j])%mod;//now表示的为i+1层可以选的总数  
        }  
        last=now;   
    }  
    
    int ans=0;  
    f(i, 1, k) ans=(ans+dp[n][i])%mod;  
    cout<<ans<<endl;  
    return 0;  
}  




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值