0
点赞
收藏
分享

微信扫一扫

蓝桥杯题选(C++ A组)

梦为马 2022-02-23 阅读 91
蓝桥杯c++

2021

砝码称重

砝码称重https://www.acwing.com/problem/content/3420

略有变形的01背包问题

先把所有砝码可能达到的最大总重sum计算出来,每次多讨论一个砝码时枚举1~sum之间的所有数,如果被标记过(表明之前已经得到过这个重量),我们可以在此数基础上加上当前砝码重量/减去当前砝码重量,并对得到的数值进行标记,并把当前讨论的砝码的单独的重量打上标记,这样一层一层推进。

#include<bits/stdc++.h>
using namespace std;
int n,a[110],ok[100010][110],sum;

int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		sum+=a[i];
	}
	ok[0][0]=1;
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<=sum;j++)
		{
			if(ok[j][i-1])
			{
				ok[j+a[i]][i]=1;
				ok[abs(j-a[i])][i]=1;
				ok[j][i]=1;
			}
		}
		ok[a[i]][i]=1;
	}
	int ans=0;
	for(int i=1;i<=sum;i++)
		if(ok[i][n]) ans++;
	cout<<ans;
	return 0;
}

异或数列

异或数列https://www.acwing.com/problem/content/3424/

博弈问题

先判断一下每组数内的所有数是否都出现两次(异或和为0),此时为平局情况。

若不为平局,则要比谁最后可以拿到二进制下最高位的有效的1。

于是先遍历所有数,按二进制数位统计每个数位上1的个数——

  • 如果最高位的1有偶数个:无效,直接比较次最高位;

  • 如果最高位的1有奇数个:

    • 特判:如果最高位1只对应1个数,这个数一定会率先被拿走,所以是先手胜出;

    • 若n的总数为奇数个,先手先拿最高位是1的数,若后手拿最高位是0的数,先手就拿最高位是0的数,若后手拿最高位是1的数,先手就拿最高位是1的数,最后是先手胜出;

    • 若n的总数为偶数个,则含有奇数个最高位是0的数,后手有办法拿到最高位奇数个0和奇数个1,先手只能拿偶数个最高位1,后手胜出。

#include<bits/stdc++.h>
using namespace std;
int T;
int a[32];

int main()
{
	cin>>T;
	while(T--)
	{
		memset(a,0,sizeof(a));
		int n;
		cin>>n;
		int ans=0;
		for(int j=0;j<n;j++)
		{
			int x;
			cin>>x;
			ans^=x;
			for(int i=1;i<=30&&x;i++)
			{
				if(x&1) a[i]++;
				x>>=1;
			}
		}
		if(!ans) cout<<0<<endl;
		else
		{
			for(int i=30;i>0;i--)
			{
				if(a[i]==1)
				{
					cout<<1<<endl;
					break;
				}
				else if(a[i]&1)
				{
					if(n&1) cout<<1<<endl;
					else cout<<-1<<endl;
					break;
				}
			}
		} 
	}
	return 0;
}

2020

七段码

并查集

//answer :80
#include<bits/stdc++.h>
using namespace std;
int mp[8][8],vis[8],fa[8],ans=0;

int find(int x)
{
	if(fa[x]==x) return x;
	else return fa[x]=find(fa[x]);
}

void dfs(int k)
{
	if(k>7)
	{
		for(int i=1;i<=7;i++) fa[i]=i;
		for(int i=1;i<=7;i++)
		{
			for(int j=1;j<=7;j++)
			{
				if(mp[i][j]&&vis[i]&&vis[j])
				{
					int x=find(i),y=find(j);
					if(x!=y) fa[x]=y;
				}
			}
		}
		int cnt=0;
		for(int i=1;i<=7;i++)
		{
			if(vis[i]&&fa[i]==i) cnt++;
		}
		if(cnt==1) ans++;
		return;
	}
	vis[k]=1;
	dfs(k+1);
	vis[k]=0;
	dfs(k+1);
}

int main()
{
	mp[1][2]=mp[2][1]=1;
	mp[1][6]=mp[6][1]=1;
	mp[2][3]=mp[3][2]=1;
	mp[2][7]=mp[7][2]=1;
	mp[3][4]=mp[4][3]=1;
	mp[3][7]=mp[7][3]=1;
	mp[4][5]=mp[5][4]=1;
	mp[5][6]=mp[6][5]=1;
	mp[5][7]=mp[7][5]=1;
	mp[6][7]=mp[7][6]=1;
	dfs(1);
	cout<<ans;
	return 0;
}

子串分值

子串分值https://www.acwing.com/problem/content/2868/

#include<std/c++.h>
using namespace std;
const int N=1e5+5;
int pre[N],next[N],a[27];
string s;
long long ans=0;

int main()
{
	cin>>s;
	int n=s.size();	
	s=' '+s;//让下标从1开始	 
	for(int i=1;i<=n;i++)
	{
		pre[i]=a[s[i]-'a'];
		a[s[i]-'a']=i;
	}//滚动一轮,得到pre数组 
	for(int i=0;i<26;i++)
		a[i]=n+1;//为了让next有初始的值(最后) 
	for(int i=n;i>0;i--)
	{
		next[i]=a[s[i]-'a'];
		a[s[i]-'a']=i;
	}//滚动一轮,得到next数组 
	for(int i=1;i<=n;i++)
		ans+=(i-pre[i])*(next[i]-i)
	//每个字符(设为ch)有一个贡献的区间 (上次出现ch的位置,下次出现ch的位置) 
	//从区间( pre[i],i)内任选一点, 从区间( next[i],i)内任选一点,s[i]在这样的两点构成的区间内只出现一次
	//对于s[i],符合条件的区间有 (i-pre[i])*(next[i]-i)个 
	cout<<ans; 
	return 0;
}

2019

迷宫

answer:DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR

典型的·BFS,值得关注的就是这种记录路径的办法。

#include<bits/stdc++.h>
using namespace std;

struct position
{
	int x,y;
	string path;
};

int maze[55][55];
int vis[55][55];
int dx[4]={1,0,0,-1};
int dy[4]={0,-1,1,0};
char direction[4]={'D','L','R','U'};

vector<char>vec;
queue<position>q;

bool judge(position next)
{
	if(!maze[next.x][next.y]&&next.x>=1&&next.x<=30&&next.y>=1&&next.y<=50&&!vis[next.x][next.y])
		return true;
	return false;
}

void bfs()
{
	position start;
	start.x=1,start.y=1;
	q.push(start);
	while(q.size())
	{
		position now=q.front();
		q.pop();
		if(now.x==30&&now.y==50)
		{
			cout<<now.path;
			return;
		}
		vis[now.x][now.y]=1;
		for(int i=0;i<4;i++)
		{
			position next;
			next.x=now.x+dx[i];
			next.y=now.y+dy[i];
			next.path=now.path+direction[i];
			if(judge(next)) q.push(next);
		}
	}
}

int main()
{
	for(int i=1;i<=30;i++)
		for(int j=1;j<=50;j++)
			scanf("%1d",&maze[i][j]);
	bfs();
	return 0;
}

外卖店优先级

外卖店优先级https://www.acwing.com/problem/content/1243/

直接暴力肯定超时,我想着写O(m)的做法,结果错了六发。。。(腹诽:还不如暴力骗80分)要注意的小细节非常多。

大体的思路就是先把题给的数据存到对应编号的vec里,然后遍历这n家外卖店的vec,对于每家店的vec:

1.先把所有数据排序!(题目给的订单不是按照时间顺序排列的)

 sort(vec[i].begin(),vec[i].end());

2.第一个数据:除了加2个优先级之外啥也不干(在第一个订单出现之前优先级一直都是0)

3.从第二个数据(如果存在的话)一直到最后一个数据:每次先处理空档造成的优先级下降(从vec[i][j]到vec[i][j-1]有(vec[i][j]-vec[i][j-1]-1)个时间段),如果优先级下降到小于等于3,标记被清出优先缓存,又由于当前订单会使得优先级加2,如果优先级大于5了,标记进入优先缓存。

 if(vec[i][j]-vec[i][j-1]-1>0)
     priority=max(0,priority-(vec[i][j]-vec[i][j-1]-1));
 if(priority<=3) flag=0;
 priority+=2;
 if(priority>5) flag=1;

3.从最后一个数据到T个时刻过去:从最后一个数据到T之间还有(T-vec[i][vec[i].size()-1])个时间段,会使优先级下降,最后判断一下是否会下降到小于等于3即可

 priority=max(0,priority-(T-vec[i][vec[i].size()-1]));
 if(priority>3&&flag) cnt++;

全部代码:

#include<bits/stdc++.h>
using namespace std;
vector<int>vec[100001];
int N,M,T,cnt;

int main()
{
	cin>>N>>M>>T;
	while(M--)
	{
		int t,num;
		scanf("%d%d",&t,&num);
		vec[num].push_back(t);
	}
	for(int i=1;i<=N;i++)
	{
		if(vec[i].empty()) continue;
		sort(vec[i].begin(),vec[i].end());
		int priority=0,flag=0;
		for(int j=0;j<vec[i].size();j++)
		{
			//cout<<vec[i][j]<<' ';
			if(j==0)
			{
				priority+=2;
				continue;
			}
			if(vec[i][j]-vec[i][j-1]-1>0)
				priority=max(0,priority-(vec[i][j]-vec[i][j-1]-1));
			if(priority<=3) flag=0;
			priority+=2;
			//cout<<" priority:"<<priority<<' ';
			if(priority>5) flag=1;
		}
		priority=max(0,priority-(T-vec[i][vec[i].size()-1]));
		//cout<<"last:"<<priority<<endl;
		if(priority>3&&flag) cnt++;
	}
	cout<<cnt;
	return 0;
}

修改数组

修改数组https://www.acwing.com/problem/content/1244/

#include<bits/stdc++.h>
using namespace std;
int N;
int a[100001],fa[2000000];
int find(int x)
{
	if(fa[x]==x) return x;
	else return fa[x]=find(fa[x]);
}

int main()
{
	cin>>N;
	for(int i=1;i<=2000000;i++) fa[i]=i;
	for(int i=1;i<=N;i++)
	{
		scanf("%d",&a[i]);
		if(find(a[i])==a[i])
			fa[a[i]]++;
		else 
		{
		    a[i]=find(a[i]);
			fa[a[i]]++;
		}
		cout<<a[i]<<' ';
	}
	return 0;
} 
举报

相关推荐

0 条评论