2022 RoboCom 世界机器人开发者大赛-本科组(省赛)已完结

目录

1. 不要浪费金币

具体实现代码:

2. 智能服药助手

具体代码实现:

3. 跑团机器人

具体代码实现:

4. 攻略分队

具体代码实现:

5. 树与二分图

具体代码实现:


1. 不要浪费金币

输入样例:

10 10
1 2 3 4 1 2 3 5 11 1

输出样例:

4

具体实现代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(void){
	ll n,m;
	ll ans=0;  //最终次数
	ll sums=0;
	cin>>n>>m;
	for(int i=0;i<n;i++){
		int t;
		cin>>t;
		if(sums+t>m){
			ans++;
			sums=t;
		}else{
			sums+=t;
		}
	}
	cout<<ans;
	return 0;
} 

2. 智能服药助手

输入样例:

10 6
1 2 3 4 5 -1 -1 -1 -1 -1
0 1 1
1 2 1 2
2 1 2
3 2 1 3
5 3 1 3 4
6 2 1 4

输出样例:

Don't take 2 at 2!
Don't take 3 at 5!
Don't take 4 at 6!

具体代码实现:

//思路:计算每个药品的间隔时间,如果小于规定时间就错误
//1. 怎么计算间隔时间-->a[药品]=时间,默认为-1(表示还未服用) 
//如果没有时间要求就不参与计算
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1010;
ll st[N];  //记录每个药品的间隔时间 
ll a[N];  //药品的吃药时间 
int main(void){
	ll n,m;
	memset(a,-1,sizeof(a));  //-1表示还未服用 
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>st[i];
	} 
	for(int i=0;i<m;i++){  //吃药记录 
		ll t,k;
		cin>>t>>k;
		for(int j=0;j<k;j++){
			int r;   //吃的药品 
			cin>>r;
			if(st[r]!=-1){  //药品如果有时间要求  
				if(a[r]!=-1){  //之前服用过该药品 
					ll cha=t-a[r];  //计算时间间隔 
					if(cha<st[r]){
						cout<<"Don't take "<<r<<" at "<<t<<"!"<<endl;
					}else{
						a[r]=t;
					}	
				}else{
					a[r]=t;
				} 		
			}
		}
	}	
	return 0; 
} 

3. 跑团机器人

    输入样例:

d6+3d5+2-2d3+2d5

    输出样例:

3 2
5 5
6 1
2 31

具体代码实现:

需要考虑到输入字符串开头带+/-符号,例如”+3d4+5“,"-3d4+5"

//思路:
//1. 需要将string类型的每一项分开
//2. map<ll,ll>存储面数+个数(map自动带有从小到大排序) 
//3. 最大值最小值一并计算 
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
map<ll,ll>mp; //面数+个数 
ll mmax=0,mmin=0;  //最大值、最小值 
int main(void){
	string s;
	cin>>s;
	//1.将字符串的每一项进行拆分
	int a=0,b=0;  //双指针
	while(b<s.size()){
		if(b!=0&&(s[b]=='+'||s[b]=='-'||b+1==s.size())){
			if(b+1==s.size())
				b++;
			string s1=s.substr(a,b-a);   //找到每一项
			a=b;
			//2. 每一项进行拆分
			int t=s1.find('d'); //找到每一项中间d
			if(t!=string::npos){  //找到了 
				string s2=s1.substr(t+1);  //面数 
				string s3=s1.substr(0,t);  //个数 
				ll n,m;  //个数、面数
				m=stoi(s2);
				if(s3.empty()){  //开头省略1
					n=1;
				}else if(s3.size()==1){  //中间省略1
					if(s3[0]=='+')
						n=1;
					else
						n=-1;
				}else{
					n=stoi(s3);
				}
				mp[m]+=abs(n);
				if(n>0){
					mmax+=n*m;
					mmin+=n*1;
				}else{
					mmax+=n*1;
					mmin+=n*m;
				}	 
			}else{   //表示是一个值 
				mmax+=stoi(s1);
				mmin+=stoi(s1); 
			}  
		}
		b++;
	} 
	for(auto it:mp){
		cout<<it.first<<" "<<it.second<<endl;
	}
	cout<<mmin<<" "<<mmax;	
	return 0;
} 

tips:

1. s.find(a)函数可以寻找a(字符/字符串)在字符串s的位置,能找到则返回第一次出现的位置(字符串a的话返回的即是字符串的首地址),找不到则返回string::npos.

4. 攻略分队

   输入样例1:

6 8 7 5 3 0
010
101
110
001
111
000

   输出样例1:

2 3
1 4 5

输入样例2:

6 8 7 5 3 0
010
101
010
001
011
000

输出样例2:

GG

具体代码实现:

//思路:
//1.怎么将随机分组所有的情况弄出来
//->左移和右移+与运算
//2. 怎么判断不唯一
//->另取一个值为okk
//3. 怎么实现规则的先后
//->优先级
#include<bits/stdc++.h>
using namespace std;
int v[7];
vector<int> q;  //存储存在的组号,便于后续分组  
int r[7][3];  //存储每一个角色(行标从1开始) 
vector<int> a,b;  //存储最优的分组情况 
int ok=-1,okk=-1;  //优先级,判断是否唯一 
int cha=10000,vis=0;  //分组两边人数之差 
int check(vector<int> &x,vector<int>&y){
	int q1[3],q2[3];  //用于统计每支队伍的特殊角色 
	int num1=0,num2=0;  //每支队伍的人数 
	okk=-1;  //需要重置,判断是否答案不唯一 
	memset(q1,0,sizeof(q1));
	memset(q2,0,sizeof(q2));
	for(int u:x){  //u表示组号
		num1+=v[u]; 
		for(int i=0;i<3;i++){
			q1[i]+=r[u][i]; 
		} 
	}
	for(int u:y){
		num2+=v[u];
		for(int i=0;i<3;i++)
			q2[i]+=r[u][i]; 
	} 
	//0.必须满足基础条件(至少有一个MT) 
	if(!q1[0]||!q2[0]) return 0;
	//1.规则1->优先级为2 
	if(q1[1]&&q1[2]&&q2[1]&&q2[2]){
		if(ok<2){
			ok=2;
			cha=abs(num1-num2);
			vis=num1>=num2?1:0;
			return 1;
		} 
		okk=2;   //第二次满足规则1时,okk=ok; 
	}else if(q1[2]&&q2[2]){  //规则2->优先级为1 
		if(ok<1){
			ok=1;
			cha=abs(num1-num2);
			vis=num1>=num2?1:0;
			return 1;
		}
		okk=1; 
	}else if(q1[0]&&q2[0]){   //规则0->优先级为0 
		if(ok<0){
			ok=0;
			cha=abs(num1-num2);
			vis=num1>=num2?1:0;
			return 1;
		}
		okk=0;
	}
	//规则012不唯一的时候 
	if(ok==okk){
		int ncha=abs(num1-num2);
		if(ncha<cha){  //规则3 
			cha=ncha;
			vis=num1>=num2?1:0;
			return 1;
		}
		if(ncha==cha){  //规则3不唯一 
			int nvis=num1>=num2?1:0;
			if(nvis>vis){   //规则4 
				vis=nvis;
				return 1;
			}
			if(nvis==vis){
				return x<a;
			} 
		}
	}
	return 0; 
} 
int main(void){
	string s;
	for(int i=1;i<=6;i++){
		cin>>v[i];
		if(v[i]>0)
			q.push_back(i);
	}
	for(int i=1;i<=6;i++){
		cin>>s;
		for(int j=0;j<3;j++){
			r[i][j]=s[j]-'0';
		}
	} 
	//1. 随机分组,列出所有可能的情况
	int n=q.size();
	vector<int> x,y; //存储分组的组号。
	for(int i=1;i<(1<<n);i++){
        x.clear();
        y.clear();
		for(int j=0;j<n;j++){  //j用来得到每一位的数值 
			if((i>>j)&1){    //&运算只看最后一位 
				x.push_back(q[j]); 
			}else{
				y.push_back(q[j]);
			} 
		}
		if(check(x,y)){
			a=x;
			b=y;
		}
	}
	//得到最终结果
	if(!a.size()||!b.size()){
		cout<<"GG";
		return 0;
	}
	for(int i=0;i<a.size();i++){
		if(i!=0) cout<<" ";
		cout<<a[i];
	}
	cout<<endl;
	for(int i=0;i<b.size();i++){
		if(i!=0) cout<<" ";
		cout<<b[i];
	}
	return 0;
} 

5. 树与二分图

输入样例:

7
1 2
2 3
2 4
2 5
2 6
4 7

输出样例:

4

具体代码实现:

//思路:
//1. 大概思路 
//二分图:也就是相邻边上的点不能在同一集合中
//树也就是一个二分图->奇数层的点在一集合,偶数层在一集合
//假设偶数层even个,奇数层odd个,那么最多可以连接n*m条线
//odd*even-(n-1)->结果
//2. 存储
//n最大可以为10的6次方,故使用vector<int> f[N]
//3. 怎么确认树的奇数层和偶数层?
//遍历每一个点,如果不是父节点,与该点相邻的则是下一层的点
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
typedef long long ll;
int n;
ll odd,even;
vector<int> f[N];
void dfs(int num,int pre,int c){
	if(c%2==0)
		even++;
	else odd++;
	for(auto x:f[num]){  //f[num]表示与点num相连的点 
		if(x!=pre)
			dfs(x,num,c+1); 
	}
} 
int main(void){
	cin>>n;
	for(int i=1;i<n;i++){
		int a,b;
		cin>>a>>b;
		f[a].push_back(b);
		f[b].push_back(a);
	}
	dfs(1,-1,1);  //点的序号,父节点,第几层 
	cout<<odd*even-(n-1); 
	return 0;
} 

最后,附上题目链接:PTA | 程序设计类实验辅助教学平台 (pintia.cn)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值