2023百度之星初赛2

(该亏的钱咱是一分不省T^T

另外只会1346哦 o.0

目录

1.最小花费

 3.跳格子

4.鸡兔同笼加强版

 6.追及问题


1.最小花费

   n个3维坐标,求把它们变成其中两个一样(xy,yz,xz),另一个 i,i+1 i+2......的最小花费

  思路:模拟(将所有点移动到一点,到中间点的距离即为最小花费,等差数列直接就近移)

//zjx6666 
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=10000010;
int a[maxn];
int b[maxn];
int c[maxn];
int main()
{
    int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	  cin>>a[i]>>b[i]>>c[i]; 
	sort(a+1,a+n+1);//三个坐标间互不干扰,直接用三个数组维护 
	sort(b+1,b+n+1);
	sort(c+1,c+n+1);
	long long ans1=0,ans2=0,ans3=0;
	int s=(n+1)/2;
	for(int i=1;i<=n;i++)
	{
		ans1=ans1+abs(a[i]-a[s])+abs(b[i]-b[s])+abs(c[i]-(c[s]-s+i));//我懒得想就直接按题意模拟了 
		ans2=ans2+abs(a[i]-a[s])+abs(c[i]-c[s])+abs(b[i]-(b[s]-s+i));
		ans3=ans3+abs(b[i]-b[s])+abs(c[i]-c[s])+abs(a[i]-(a[s]-s+i));
	}
	long long ans=min(ans1,ans2);
	ans=min(ans2,ans3);
	cout<<ans;//三种情况取个最小 
	return 0;
}

 3.跳格子

跳格子,可向前1向后1或者瞬移到前面第一个值相同的(花费均为1)问到n的最小花费

 思路:无权边最短路,直接无脑建边BFS

//zjx6666
#include<iostream>
#include<map>
#include<vector>
#include<queue>
using namespace std;
const int maxn=200100;
int a[maxn];
map<int,int>mp;
queue<int>q;
bool v[maxn];
int d[maxn];
vector<int>e[maxn];
int bfs(int x,int y)//无权最短路,简单的bfs(迪杰斯特拉也可,稍微麻烦一点) 
{
	q.push(x);
	v[x]=1;
	d[x]=0;
	while(q.size())
	{
		int z=q.front();
		q.pop();
		for(int i=0;i<e[z].size();i++)
		{
			if(!v[e[z][i]])
			{
			    if(e[z][i]==y)return (d[z]+1);
				v[e[z][i]]=1;
				d[e[z][i]]=d[z]+1;
				q.push(e[z][i]);
			}
		}
	}
}
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		if(!mp.count(a[i]))
		{
			mp[a[i]]=i;
		}
		else
		{
			e[mp[a[i]]].push_back(i);//mp中存的上一个与它值相等的点的编号 
			mp[a[i]]=i;//记得更新mp 
		}
		if(i>1)e[i].push_back(i-1);
		if(i<n)e[i].push_back(i+1);//与其前后点建边 
	}
	cout<<bfs(1,n);
	return 0;
}
	
		

2024.4.24增加人类智慧dp版本做法

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fast ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
void solve();
using pii = pair<int, int>; 
using db = double;
signed main(){
	fast
	int t = 1;
//	cin >> t;
	for(int i = 1; i <= t; i++){
		solve();
	}
}
 
const int N = 3e5 + 10, M = N * 2, P = 998244353;
 
int n, a[N];
int f[N], pos[N];
 
void solve(){
	cin >> n;
	int id=0;
	for(int i = 1; i <= n; i++) cin >> a[i];
	memset(f, 0x3f, sizeof f);
	memset(pos, -1, sizeof pos);
	f[0] = -1;
	for(int i = 1; i <= n; i++){
		int mn = f[i - 1] + 1;
		if(pos[a[i]] != -1) mn = min(mn, f[pos[a[i]]] + 1);
		f[i] = mn;
      	if(i > 1 && f[i] < f[i - 1] - 1){
        		for(int j = i - 1; j >= 1&&f[j]>mn+i-j; j--){
				f[j] = min(f[j], mn + i - j);
				id++;
			}
        }
		pos[a[i]] = i;
	}
	cout << f[n];
}

4.鸡兔同笼加强版

  鸡兔同笼3人版,n头m脚三种动物abc个脚,问c个脚的最少几只最多几只

  思路:发现n只有1e4,果断枚举两个判另外一个是否符合条件(这场题好像比第一场水一点)

//zjx6666
#include<iostream>
using namespace std;
int main()
{
	long long n,m,a,b,c,v=0;
	long long ans1=n,ans2=0;
	cin>>n>>m>>a>>b>>c;
	for(long long i=0;i<=n;i++)
	{
		for(long long j=0;j<=n-i;j++)
		{
		    long long s=m-(i*a+(j*b));
			if(s>=0&&s%c==0&&i+j+(s/c)==n)//注意判下大于0,不幸在此哇一发 
			{
				v=1;
				ans1=min(s/c,ans1);
				ans2=max(s/c,ans2);
			}
		}
	}
	if(v==0)cout<<-1;
	else cout<<ans1<<" "<<ans2;
	return 0;
}

 6.追及问题

   n个人每人一个初始位置x一个速度v,两人跑到同一位置时速度都变为小的那个(一起走,变为一组),问最多的一组几个人

 思路:首先简单推一下,当xi<=xj并vi>vj时j一定会被i追上

     首先考虑速度最小的一个点 i 一定会在某时刻被他前面的所有点追上(因为 i 速度最小),而他永远也追不上他后面的,由于 i 前面的点在与他相遇后速度合并为最小的v,所以也追不上 i 后面的点,这样所有位置在 i 之前的点就能组成一个集合,然后 i 后面的同理操作,找没有被 i 合并的下一个最小值,组成新的集合,取最大的就是答案

    这样就有思路啦,我一开始n^2实现tle了(还是不能偷懒)老老实实排两次序吧T-T

   comp1是为了提前算出对于每个编号为id的点,他的前面有几个点,这样可以在查找时避免循环的嵌套。然后第二次排序用v排(即速度小的在前),这样可以保证速度最小的先合并完(这样出来的集合是完整的)

//zjx6666
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
int n;
const int maxn=100010;
map<int,int>mp;
struct A{int x,v,id;};
A e[maxn];
int comp1(A p,A q)
{
	if(p.x==q.x)return p.v>q.v;//注意x相等速度小的合并速度大的 
	return p.x<q.x;
}
int comp(A p,A q)
{
	if(p.v==q.v)return p.x<q.x;//注意v相等前面的合不了后面的(平行) 
	return p.v<q.v;//这样保证了位置小的先合,方便维护 
}
int main()
{
	ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>e[i].x>>e[i].v;
		e[i].id=i;//记录一下编号 
	}
	sort(e+1,e+n+1,comp1); 
	for(int i=1;i<=n;i++)
		mp[e[i].id]=i;//第一次排序为了记录第i个点前面有几个点(包括自己)方便o(n)实现 
	sort(e+1,e+n+1,comp);
	int ans=0,l=0,s=0;//l为上一次合到的位置,s是之前合了几个 
	for(int i=1;i<=n;i++)//第二次排序完后速度小的在前,一定可以合并x在自己之前并且没被合并的 
	{
		if(e[i].x>l)
		{
			ans=max(ans,mp[e[i].id]-s);
			l=e[i].x;
			s=mp[e[i].id];
		}
		
	}
	cout<<ans;
	return 0;
}
			

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
百度之星题集 PDF是一本包含了百度之星竞赛历年题目的电子书,通过PDF的形式提供给参赛者进行学习和复习。百度之星是由百度公司主办的一项面向全球大学生的计算机编程竞赛,旨在发现和培养优秀的计算机人才。 这本题集的目的是帮助参赛者更好地了解竞赛的题型和要求,学习和掌握相关的知识和技能。题集中包含了题目的详细描述、输入输出样例、解题思路和参考代码等内容,使参赛者能够更高效地准备和应对竞赛。 通过使用百度之星题集PDF,参赛者可以进行以下方面的学习和提高: 1. 熟悉题目类型和难度:题集收录了历年竞赛的题目,参赛者可以通过研究不同题目类型和难度,了解到哪些知识点和技巧经常被考察,从而有针对性地准备和复习。 2. 掌握解题思路和方法:题集中给出了详细的解题思路和方法,包括如何分析问题、设计算法和实现代码等。参赛者可以借鉴这些思路和方法,提高解题的效率和质量。 3. 增强编程技能和实战能力:通过练习题集中的题目,参赛者可以不断提高自己的编程技能和实战能力,熟练掌握各种编程语言和数据结构,为竞赛中的表现做好准备。 4. 提升团队协作和竞赛素养:百度之星是一个团队竞赛,参赛者可以通过研究题集中的题目,了解和学习团队协作和竞赛素养,提高团队的配合和表现。 总之,百度之星题集PDF是一本有助于参赛者更好地准备和复习百度之星竞赛的资料。通过合理使用这本题集,参赛者可以提高解题的能力和竞赛的表现,增加在竞争中脱颖而出的机会。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值