2025年(RAICOM)睿抗机器人开发者大赛CAIP国赛题解

RC-u1 谁拿冠军了?

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

很久没敲代码,第一题写法太唐了,花的时间也很多。

利用结构体和map,存储每一天的操作,使用数组也可以。

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int n,m,a1,a2,b1,b2,b3;
int ans1,ans2;
struct nod{
	int c1;
	int c2;
	int c3;
};
unordered_map<int,nod> mp;
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n>>m;
	cin>>a1>>a2>>b1>>b2>>b3;
	for(int i=1;i<=n;i++){
		int d,op;cin>>d>>op;
		if(op==1) mp[d].c1++;
		else if(op==2) mp[d].c2++;
		else mp[d].c3++;
	}
	for(int i=1;i<=m;i++){
		int t,op;cin>>t>>op;
		int tmp1=0,tmp2=0;
		if(op==1&&mp[t].c1!=0){
			tmp1=mp[t].c1*a1;
			tmp2=mp[t].c1*b1;
			tmp2/=2;
			ans1+=tmp1,ans2-=tmp2;
			mp[t].c1=0;
		}else if(op==2&&mp[t].c2!=0){
			tmp2=mp[t].c2*b2;
			tmp2/=2;
			ans2-=tmp2;
			mp[t].c2=0;
		}else if(op==3&&mp[t].c3!=0){
			tmp1=mp[t].c3*a2;
			tmp2=mp[t].c3*b3;
			tmp2/=2;
			ans1-=tmp1,ans2-=tmp2;
			mp[t].c3=0;
		}
	}
	unordered_map<int,nod>::iterator it=mp.begin();
	for(;it!=mp.end();it++){
		nod d=(*it).second;
		int tmp1,tmp2;
		if(d.c1!=0){
			tmp1=d.c1*a1;
			tmp2=d.c1*b1;
			ans1+=tmp1,ans2-=tmp2;
		}
		if(d.c2!=0){
			tmp2=d.c2*b2;
			ans2-=tmp2;
		}
		if(d.c3!=0){
			tmp1=d.c3*a2;
			tmp2=d.c3*b3;
			ans1-=tmp1,ans2-=tmp2;
		}
	}
	cout<<ans1<<" "<<ans2;
	return 0;
}

RC-u2 理包

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

一开始思路错了,等想到正确思路时,已经过去二十分钟了。

我使用一个c数组存储每次输入图形,再去除掉周围空白的,压缩到b数组中,再一个个点尝试放入a数组中。代码还可以更简单。

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int N,M,n,m,q,sh,sl,zz,yy,ss,xx;
int a[55][55],b[55][55],c[55][55];
bool pan(int x,int y){
	for(int i=1;i<=xx-ss+1;i++){
		for(int j=1;j<=yy-zz+1;j++){
			if(x+i-1>N||y+j-1>M) return 0;
			if(b[i][j]==1&&a[x+i-1][y+j-1]==1) return 0;
		}
	}
	return 1;
}
void cha(int x,int y){
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(b[i][j]) a[x+i-1][y+j-1]=1;
		}
	}
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>N>>M>>q;
	while(q--){
		yy=xx=sh=sl=0;
		zz=ss=0x3f3f3f3f;
		cin>>n>>m;
		memset(b,0,sizeof(b));
		memset(c,0,sizeof(c));
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				char ch;cin>>ch;
				if(ch=='*'){
					c[i][j]=1;
					if(sh==0){sh=i,sl=j;}
					zz=min(zz,j),yy=max(yy,j),ss=min(ss,i),xx=max(xx,i);
				}
			}
		}
		for(int i=1;i<=xx-ss+1;i++)
			for(int j=1;j<=yy-zz+1;j++)
				b[i][j]=c[ss+i-1][zz+j-1];
		sh-=ss-1,sl-=zz-1;
		int f=0;
		for(int i=1;i<=N;i++){
			if(f) break;
			for(int j=1;j<=M;j++){
				if(f) break;
				if(pan(i,j)){
					cha(i,j);
					f=1;
					cout<<i+sh-1<<" "<<j+sl-1<<"\n";
				}
			}
		}
		if(!f) cout<<"-1 -1\n";
	}
	return 0;
}

RC-u3 删除屏蔽词

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

这题应该是国赛签到题。

下面首先是我赛时愚蠢代码,再是AC代码。

赛时我没看到第一个字符串长度为2的条件,想骗点分赶快去写第4题,因此直接循环find,总共耗时几分钟就跳了。只拿到15分,亏麻了。
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
string s,str;
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>s>>str;
	int tmp=str.find(s),ans=0;
	while(tmp!=-1){
		string s1=str.substr(0,tmp);
		string s2=str.substr(tmp+s.size());
		str=s1+s2;
		ans++;
		tmp=str.find(s);
	}
	cout<<ans<<" "<<str;
	return 0;
}

赛后队友刘神说AC了,讨论了一下发现我眼瞎。

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
char s[2],str[1000001],x;
int len,ans;
int main(){
	cin>>s[0]>>s[1];
	str[0]=' ';
	while(cin>>x){
		if(x==s[1]&&str[len]==s[0]){
			ans++,len--;
		}else{
			str[++len]=x;
		}
	}
	str[len+1]='\0';
	cout<<ans<<str;
	return 0;
}

RC-u4 穷游

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

首先说明,我下面代码只拿到28分,有一个特例没拿到,没时间改bug,想AC的自己找找。

因为题目要求路径最贵城市的费用尽可能少,所以我们从费用低的城市到费用高的城市一个个找,当起点到终点出现路径时,此时这个路径的最贵城市费用最低。我们再利用比这个费用低的所有城市找出最短路径即可。

我首先利用结构体排序,得到费用从低到高,再利用并查集,一个个加入直至得到起点终点联通,再通过最短路板子得到最短路径即可。

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+10,M=3e4+10;
struct edge{
	int v,w;
};
struct nod{
	int len,v;
	friend bool operator > (nod a,nod b){
		return a.len>b.len;
	}
};
vector<edge> vt[N];
int n,m,s,dis[N],vis[N],S,T,tmpz;
int f[N];
int bfind(int x){
	if(f[x]!=x) f[x]=bfind(f[x]);
	return f[x];
}
struct cs{
	int id,cc,gd;
}c[N];
bool cmp(cs a,cs b){
	if(a.cc!=b.cc) return a.cc<b.cc;
	return a.id<b.id;
}
unordered_map<int,int> ump;
priority_queue<nod,vector<nod>,greater<nod> > q;
void dijkstra(){
	memset(dis,0x3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	dis[S]=0;
	q.push({0,S});
	while(!q.empty()){
		int u=q.top().v;q.pop();
		if(vis[u]) continue;
		vis[u]=1;
		for(int i=0;i<vt[u].size();i++){
			int v=vt[u][i].v,z=vt[u][i].w;
			if(v>tmpz) continue;
			if(dis[v]>dis[u]+z){
				dis[v]=dis[u]+z;
				q.push({dis[v],v});
			}
		}
	}
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>c[i].cc;
		c[i].id=i;
		f[i]=i;
	}
	sort(c+1,c+n+1,cmp);
	for(int i=1;i<=n;i++) ump[c[i].id]=i;
	for(int i=1;i<=m;i++){
		int v3,v4,t;cin>>v3>>v4>>t;
		int v1=ump[v3],v2=ump[v4];
		vt[v1].push_back({v2,t});
		vt[v2].push_back({v1,t});
	}
	cin>>S>>T;
	S=ump[S],T=ump[T];
	//1.从小到大扩展并查集,直到st出现路径
	for(int i=1;i<=n;i++){
		for(int j=0;j<vt[i].size();j++){
			if(vt[i][j].v<=i){
				int fi=bfind(i),fj=bfind(vt[i][j].v);
				if(f[fi]!=f[fj]) f[fj]=f[fi];
			}
		}
		if(bfind(S)==bfind(T)){
			tmpz=i;
			break;
		}
	}
	//2.st的连通块中找出最短路
	dijkstra();
	cout<<c[tmpz].cc<<" ";
	cout<<dis[T]<<"\n";
	return 0;
}

RC-u5 工序优化

在这里插入图片描述

在这里插入图片描述

最后时间不够了,这题花了10min不到,写了个贪心拿到14分也差不多了。按照往年最后一题,这题正解应该是DP。(向天再借20min我应该能写个DP出来分更高
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+10;
int n,k,tmp;
ll t[N],p[N],c[N],ans1,ans2;
int main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>t[i]>>p[i]>>c[i];
	}
	ans1=t[1]*p[1];
	for(int i=2;i<=n;i++){
		ll tmp1=t[i-1]*p[i],tmp2=t[i]*p[i];
		if(tmp1<tmp2&&k){
			ans1+=tmp1;
			ans2+=c[i];
			k--;
			t[i]=t[i-1];
		}else ans1+=tmp2;
	}
	cout<<ans1<<" "<<ans2<<"\n";
	return 0;
}

总结,这写代码写完后,晚上被子里都是甜的,太唐了。

相较于去年,第三题纯亏麻了,第四题比去年拿分更多,第五题比去年拿分更少。