牛客刷题 - 2017百度春招(暴力 & 思维 & dp)

版权声明:如果感觉写的不错,转载标明出处链接哦~blog.csdn.net/wyg1997 https://blog.csdn.net/wyg1997/article/details/82846690

一共五道题,前三道没什么难度,暴力枚举就可以了。后两道需要想想,但是也不难(dp还是我的弱项啊)


Q1:

在这里插入图片描述

解题思路:这个没什么说的,随便都能过。

代码如下:

#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define CLR(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
int main()
{
	int n;
	int pr[55];
	while (~scanf("%d",&n))
	{
		for (int i = 0 ; i < n ; i++)
			scanf("%d",&pr[i]);
		sort(pr, pr+n);
		int temp = pr[0];
		int cnt = 1;
		for (int i = 1 ; i < n ; i++)
		{
			if (pr[i] != temp)
			{
				temp = pr[i];
				cnt++;
				if (cnt == 3)
				{
					temp = pr[i];
					break;
				}
			}
		}
		printf("%d\n",cnt==3 ? temp : -1);
	}
	return 0;
}


Q2:

在这里插入图片描述

解题思路:直接枚举去掉每个点更新结果即可。

代码如下:

#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define CLR(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
int main()
{
	int n;
	int pos[55];
	while (~scanf("%d",&n))
	{
		int all = 0;
		for (int i = 0 ; i < n ; i++)
		{
			scanf ("%d",&pos[i]);
			if (i >= 1)
				all += abs(pos[i]-pos[i-1]);
		}
		int ans = all;
		for (int i = 1 ; i < n-1 ; i++)
			ans = min(ans, all-abs(pos[i]-pos[i-1])-abs(pos[i+1]-pos[i])+abs(pos[i+1]-pos[i-1]));
		printf("%d\n",ans);
	}
	return 0;
}


Q3:

在这里插入图片描述

解题思路:分两种情况,同一个颜色和不同颜色的,然后遍历求面积就行,海伦公式~

代码如下:

#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define CLR(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
struct Point
{
	double x,y,z;
};
double dis(Point a, Point b)
{
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
}
double get_S(Point a, Point b, Point c)
{
	double da, db, dc;
	da = dis(b,c);
	db = dis(a,c);
	dc = dis(a,b);
	double k = (da+db+dc)/2;
	return sqrt(k*(k-da)*(k-db)*(k-dc));
}
int main()
{
	int n;
	while (~scanf("%d",&n))
	{
		vector<Point> R;
		vector<Point> G;
		vector<Point> B;
		Point tp;
		for (int i = 0 ; i < n ; i++)
		{
			char kind[4];
			scanf("%s %lf %lf %lf",kind,&tp.x,&tp.y,&tp.z);
			if (kind[0] == 'R')
				R.push_back(tp);
			else if (kind[0] == 'G')
				G.push_back(tp);
			else
				B.push_back(tp);
		}
		double ans = 0;
		//先枚举同一个颜色
		//R
		for (int i = 0 ; i < R.size() ; i++)
		{
			for (int j = i+1 ; j < R.size() ; j++)
			{
				for (int k = j+1 ; k < R.size() ; k++)
					ans = max(ans, get_S(R[i], R[j], R[k]));
			}
		}
		//G
		for (int i = 0 ; i < G.size() ; i++)
		{
			for (int j = i+1 ; j < G.size() ; j++)
			{
				for (int k = j+1 ; k < G.size() ; k++)
					ans = max(ans, get_S(G[i], G[j], G[k]));
			}
		}
		//B
		for (int i = 0 ; i < B.size() ; i++)
		{
			for (int j = i+1 ; j < B.size() ; j++)
			{
				for (int k = j+1 ; k < B.size() ; k++)
					ans = max(ans, get_S(B[i], B[j], B[k]));
			}
		}
		
		//再枚举三种颜色
		for (int i = 0 ; i < R.size() ; i++)
		{
			for (int j = 0 ; j < G.size() ; j++)
			{
				for (int k = 0 ; k < B.size() ; k++)
					ans = max(ans, get_S(R[i], G[j], B[k]));
			}
		}
		
		printf("%.5lf\n",ans);
	}
	return 0;
}


Q4:

在这里插入图片描述
解题思路:这道题得想想了,用稳定sort排序后,从最小开始看看有多长的序列是不用动的,例如样例中:19 7 8 25,可见7 8两个数字的位置是正确的,19位置就不正确了(19应该在8后面),所以19后面的数字(19 25)都得操作一次。
再随便举个例子:2 3 45 46 47 48 49 15,从最小的数字往后看依次是2 3 15,然后再看45时发现位置不对了,所以大于等于45的都要操作。

代码如下:

#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define CLR(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
struct Num
{
	int order;
	int num;
};
bool cmp(Num a, Num b)
{
	if (a.num == b.num)
		return a.order < b.order;
	return a.num < b.num;
}
int main()
{
	int n;
	int num[55];
	int cp[55];
	while (~scanf("%d",&n))
	{
		vector<Num> d;
		Num temp;
		for (int i = 0 ; i < n ; i++)
		{
			scanf("%d",&temp.num);
			temp.order = i;
			d.push_back(temp);
		}
		sort(d.begin(), d.end(), cmp);
		//上个数字的位置 
		int pos = -1;
		//正确排序的数字数 
		int ok = 0;
		for (int i = 0 ; i < n ; i++)
		{
			if (d[i].order > pos)
			{
				pos = d[i].order;
				ok++;
			}
			else
				break;
		}
		printf("%d\n",n-ok);
	}
	return 0;
}


Q5:

在这里插入图片描述
在这里插入图片描述

解题思路:考虑用动态规划:dp[i][j],i表示一共i个数,j表示有j个大于号(个人习惯,也可以表示小于号,其实都一样)。
下一个有i个数字、j个大于号时,考虑下面四种情况:
1.dp[i-1][j-1]状态,把i放在最前面,即可得到j个大于号,有dp[i-1][j-1]种情况。
2.dp[i-1][j-1]状态,需要增加一个大于号,把i插入小于号所在的位置时,可以多出一个大于号(例如:1<2,我们把3插入到小于号的位置上时,变成1<3>2),即在dp[i-1][j-1]个状态中每个小于号都可以插入,有dp[i-1][j-1]*(i-1-j)种状态。
3.dp[i-1][j]状态,把j放在最后面,则不会增加大于号,有dp[i-1][j]种状态。
4.dp[i-1][j]状态,类似
2的情况,这次可以在每个大于号的位置上插入数字i,有dp[i-1][j]*j种情况。

代码如下:

#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define CLR(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
int dp[1005][1005];
int main()
{
	for (int i = 1 ; i <= 1000 ; i++)
	{
		dp[i][0] = 1;
		dp[i][i-1] = 1;
		for (int j = 1 ; j < i-1 ; j++)
			dp[i][j] = (dp[i-1][j-1] + dp[i-1][j-1]*(i-1-j) + dp[i-1][j] + dp[i-1][j]*j)%2017;
	}
	int n,m;
	while (~scanf("%d %d",&n,&m))
	{
		printf("%d\n",dp[n][n-1-m]);
	}
	return 0;
}

展开阅读全文

没有更多推荐了,返回首页