2024睿抗(Raicom)机器人开发者大赛CAIP-编程技能赛-本科组 国赛 个人题解

RC-u1 大家一起查作弊

字符串持续读入,while(getlinre(cin,s))后按空格分割字符串即可。

#include<bits/stdc++.h>
using namespace std;
int judge(char c)
{
	if(c>='a'&&c<='z')  return 1;
	if(c>='A'&&c<='Z')  return 1;
	if(c>='0'&&c<='9')  return 1;
	return 0;
}
int main()
{
	string s;
	vector<string>v;
	int cnt=0;
	while(getline(cin,s))
	{
		int n=s.length();
		s+='?';
		string str="";
		for(int i=0;i<n;i++)
		{
			for(int j=i;j<=n;j++)
			{
				if(!judge(s[j]))
				{
					if(str.length())  v.push_back(str);
					str="";
					i=j;
					break;
				}
				str+=s[j];
			}
		}
	}
	int x=0,y=0;
	for(auto str:v)
	{
		int n=str.length();
		int f1=0,f2=0,f3=0;
		for(int i=0;i<n;i++)
		{
			char c=str[i];
			if(c>='a'&&c<='z')  f1=1;
			if(c>='A'&&c<='Z')  f2=1;
			if(c>='0'&&c<='9')  f3=1;
		}
		if(f1&&f2&&f3)  x+=5;
		else if((f2&&f3)||(f1&&f3))  x+=3;
		else if(f1&&f2)  x++;
		y+=n;
	}
	cout<<x<<endl<<y<<" "<<v.size();
}

RC-u2 谁进线下了?II

模拟,为了减少代码量可以发现后面十几名的分数都是有规律的:分数与名次之和为20.

#include<bits/stdc++.h>
using namespace std;
struct node{
	int x,idx,flag;
}a[35];
bool cmp(node A,node B)
{
	if(A.x==B.x)  return A.idx<B.idx;
	return A.x>B.x;
}
int f(int x)
{
	if(x==1)  return 25;
	else if(x==2)  return 21;
	else if(x==3)  return 18;
	else  return 20-x;
}
int main()
{
	int t;
	cin>>t;
	for(int i=1;i<=30;i++)  a[i].idx=i,a[i].flag=0;
	while(t--)
	{
		for(int i=1;i<=20;i++)
		{
			int num,y;
			cin>>num>>y;
			a[num].x+=f(y);
			a[num].flag=1;
		}
	}
	sort(a+1,a+31,cmp);
	for(int i=1;i<=30;i++)
		if(a[i].flag)  cout<<a[i].idx<<" "<<a[i].x<<endl;
}

RC-u3 势均力敌

dfs,第一次枚举排列,第二次枚举其中一个集合的元素。

据说是有规律的,n的范围可以扩大到1000.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,a[10],st[10],st2[100010],flag=0,sum=1;
vector<ll>v;
vector<ll>x,y;
void dfs(int u,int x)
{
	if(u>=n)
	{
		v.push_back(x);
		return;
	}
	for(int i=0;i<n;i++)
	{
		if(st[i])  continue;
		st[i]=1;
		dfs(u+1,x*10+a[i]);
		st[i]=0;
	}
}
void dfs2(int u)
{
	if(flag||u==v.size())  return;
	if(x.size()==sum/2)
	{
		ll s1=0,s2=0;
		for(int i=0;i<v.size();i++)
			if(!st2[i])  s2+=v[i]*v[i];
		for(auto i:x)  s1+=i*i;
		if(s1==s2)
		{
			for(auto i:x)  cout<<i<<endl;
			flag=1;
		}
		return;
	}
	x.push_back(v[u]);
	st2[u]=1;
	dfs2(u+1);
	st2[u]=0;
	x.pop_back();
	dfs2(u+1);
}
int main()
{
	memset(st,0,sizeof(st));
	memset(st2,0,sizeof(st2));
	cin>>n;
	for(int i=1;i<=n;i++)  sum*=i;
	for(int i=0;i<n;i++)  cin>>a[i];
	dfs(0,0);
	dfs2(0);
}

RC-u4 City 不 City

两种代价的dijkstra,增加一个属性后在优先队列中分别维护即可。注意一个是路径加和,另一个是点权最值。

#include<bits/stdc++.h>
using namespace std;
int n,m,s,T,a[1010],st[1010],h[1010],e[10010],ne[10010],w[10010],d1[1010],d2[1010],idx=0;
struct Node{
	int node,x,y;//x路径花费,y节点花费 
	friend bool operator<(Node A,Node B)
	{
		if(A.x==B.x)  return A.y>B.y;
		return A.x>B.x;
	}
};
void add(int a,int b,int c)
{
	e[idx]=b;
	ne[idx]=h[a];
	w[idx]=c;
	h[a]=idx++;
}
void dijkstra()
{
	priority_queue<Node>q;
	q.push({s,0,0});
	d1[s]=0,d2[s]=0;
	while(q.size())
	{
		Node t=q.top();
		q.pop();
		int u=t.node,x=t.x,y=t.y;
		if(st[u])  continue;
		st[u]=1;
		for(int i=h[u];i!=-1;i=ne[i])
		{
			int j=e[i];
			if(d1[j]>d1[u]+w[i])
			{
				d1[j]=d1[u]+w[i];
				if(T!=j)  d2[j]=max(d2[u],a[j]);
				else  d2[j]=d2[u];
				q.push({j,d1[j],max(d2[u],a[j])});
			}
			else if(d1[j]==d1[u]+w[i])
			{
				if(d2[j]>max(d2[u],a[j]))
				{
					if(T!=j)  d2[j]=max(d2[u],a[j]);
					else  d2[j]=d2[u];
					q.push({j,d1[j],max(d2[u],a[j])});
				}
			}
		}
	}
}
int main()
{
	memset(h,-1,sizeof(h));
	memset(st,0,sizeof(st));
	memset(d1,0x3f,sizeof(d1));
	memset(d2,-0x3f,sizeof(d2));
	cin>>n>>m>>s>>T;
	for(int i=1;i<=n;i++)  cin>>a[i];
	while(m--)
	{
		int x,y,z;
		cin>>x>>y>>z;
		add(x,y,z),add(y,x,z);
	}
	dijkstra();
	if(d1[T]>1e9)  cout<<"Impossible";
	else  cout<<d1[T]<<" "<<d2[T];
}

RC-u5 贪心消消乐(WA一个点)

直接暴力模拟,开一个无限循环每次暴力判断是否可以存在消掉的区域,没有了就break。为了降低时间复杂度,开两个二维前缀和数组s和f分别用于快速查询区间和以及区间黑洞的数量,每模拟一次就再更新一遍这两个数组。这个做法不会超时,但是有个点错了不知道为什么。还有注意这里的横纵坐标和我们常用的是相反的。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,a[210][210],st[210][210],s[210][210],f[210][210];
int main()
{
	memset(a,0,sizeof(a));
	memset(st,0,sizeof(st));
	memset(s,0,sizeof(s));
	memset(f,0,sizeof(f));
	cin>>n;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)  cin>>a[i][j];
	s[0][0]=0,f[0][0]=0;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)  s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			if(a[i][j]==0)  f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+1;
			else  f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
	ll ans=0;
	while(1)
	{
		int flag=0,x1=1e9,x2=1e9,y1=1e9,y2=1e9;
		ll maxx=0;
		for(int j=1;j<=n;j++)
		{
			for(int i=1;i<=n;i++)
			{
				for(int l=j;l<=n;l++)
				{
					for(int k=i;k<=n;k++)
					{
						int sum=s[k][l]-s[i-1][l]-s[k][j-1]+s[i-1][j-1];
						int F=f[k][l]-f[i-1][l]-f[k][j-1]+f[i-1][j-1];
						if(F>0)  break;
						if(sum>maxx)  x1=i,y1=j,x2=k,y2=l,maxx=sum,flag=1;
					}
				}
			}
		}
		ans+=maxx;
		if(!flag)  break;
		int h=x2-x1+1;
		for(int i=1;i<x1;i++)
			for(int j=y1;j<=y2;j++)  a[i+h][j]=a[i][j],a[i][j]=0;
		for(int i=x1;i<=x2-x1+1;i++)
			for(int j=y1;j<=y2;j++)  a[i][j]=0; 
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)  s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				if(a[i][j]==0)  f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+1;
				else  f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
		cout<<"("<<y1<<", "<<x1<<") ("<<y2<<", "<<x2<<") "<<maxx<<'\n';
	}
	cout<<ans;
}

总结:全是模拟,比cf那种数学加思维简单多了,只要基础扎实拿个100+分不是问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值