2021 RoboCom 世界机器人开发者大赛-本科组(初赛)完结
Posted 辉小歌
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021 RoboCom 世界机器人开发者大赛-本科组(初赛)完结相关的知识,希望对你有一定的参考价值。
看群友在水这个比赛玩玩,于是也去打了一下重现赛。
事实证明,群友轻松AK,而我只会暴力。
总的难度就是PAT甲的难度吧,数据很不错,恶心的一批。
补题完结
目录
7-1 懂的都懂 (20 分)【简单 / 暴力 + 哈希表】
方法一: 自己的傻叉做法 预处理所有的4个数的平均值。用double 注意精度
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m;
double a[N],b[N];
map<double,int>mp;
int main(void)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++) scanf("%lf",&a[i]);
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
for(int k=j+1;k<n;k++)
{
for(int z=k+1;z<n;z++)
{
int temp=a[i]+a[j]+a[k]+a[z];
mp[temp/4.0]++;
}
}
}
}
while(m--)
{
int t; scanf("%d",&t);
bool flag=1;
for(int i=0;i<t;i++)
{
scanf("%lf",&b[i]);
if(!mp[b[i]]) flag=false;
}
if(flag) puts("Yes");
else puts("No");
}
return 0;
}
方法二: 只需处理所有的四个数的和即可,不用求平均
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m;
int a[N],b[N];
map<int,int>mp;
int main(void)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
for(int k=j+1;k<n;k++)
{
for(int z=k+1;z<n;z++)
{
int temp=a[i]+a[j]+a[k]+a[z];
mp[temp]++;
}
}
}
}
while(m--)
{
int t; scanf("%d",&t);
bool flag=1;
for(int i=0;i<t;i++)
{
scanf("%d",&b[i]);
if(!mp[b[i]*4]) flag=false;
}
if(flag) puts("Yes");
else puts("No");
}
return 0;
}
7-2 芬兰木棋 (25 分)【中 / map 贪心】
大木棋会打倒这个方向上离哲哲最近的 k 个小木棋
读了半天的假题。
1 1 1
2 2 2
3 3 1
步数为3 先打1再2再3
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL ans,n,cnt;
LL gcd(LL a,LL b) {return b?gcd(b,a%b):a;}
map<pair<LL,LL>,vector< pair<LL,LL> > >mp;//斜率映射到对应的距离加分数
int main(void)
{
cin>>n;
for(int i=1;i<=n;i++)
{
LL x,y,c; cin>>x>>y>>c;
ans+=c;
LL temp=gcd(abs(x),abs(y));
mp[{x/temp,y/temp}].push_back({x*x+y*y,c}); //注意: 距离必须是x*x+y*y 单独的x是不行的因为还有y轴上的点
}
cnt=0;
for(auto i=mp.begin();i!=mp.end();i++)//枚举所有的方向
{
auto ve=i->second;
sort(ve.begin(),ve.end());//距离排序
for(int j=0;j<ve.size();j++)
{
if(ve[j].second!=1)
{
cnt++;
if(j-1>=0&&ve[j-1].second==1) cnt++;
}
}
if(ve[ve.size()-1].second==1) cnt++;
}
cout<<ans<<" "<<cnt;
return 0;
}
7-3 打怪升级 (25 分) 【中 / 最短路 记得维护值 和 存路径】
写的可以过,不过有点太卡时间。
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int n,m,t,x;
int g[N][N],dist[N],st[N];
int startx,maxv=1e9;
int p[N][N];
map<int,int>val,ans;//val存的是该点最大的价值,ans存路径
void Dijkstra(int x)
{
memset(dist,0x3f,sizeof dist);
memset(st,0,sizeof st);
dist[x]=0;
for(int i=0;i<n;i++)
{
int t=-1;
for(int j=1;j<=n;j++) if(!st[j]&&(t==-1 || dist[j]<dist[t] )) t=j;
st[t]=1;
for(int j=1;j<=n;j++)
{
if(dist[j]>dist[t]+g[t][j])
{
dist[j]=dist[t]+g[t][j];
val[j]=val[t]+p[t][j];
ans[j]=t;
}
else if(dist[j]==dist[t]+g[t][j])
{
if(val[j]<val[t]+p[t][j])
{
val[j]=val[t]+p[t][j];
ans[j]=t;
}
}
}
}
int temp=0;
for(int i=1;i<=n;i++) temp=max(temp,dist[i]);
if(temp<maxv) maxv=temp,startx=x;
}
int main(void)
{
memset(g,0x3f,sizeof g);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
g[a][b]=g[b][a]=c;
p[a][b]=d,p[b][a]=d;
}
for(int i=1;i<=n;i++) Dijkstra(i);//每一个点跑一下最短路,找到最短路中最大的值,最小的值
printf("%d\\n",startx);
val.clear(),ans.clear();
Dijkstra(startx);
scanf("%d",&t);
while(t--)
{
int x; scanf("%d",&x);
int node=x;
vector<int>path;
while(node)
{
path.push_back(node);
node=ans[node];
}
for(int i=path.size()-1;i>=0;i--)
{
if(i!=path.size()-1) printf("->");
printf("%d",path[i]);
}
printf("\\n%d %d\\n",dist[x],val[x]);
}
return 0;
}
7-4 疫情防控 (30 分)【难度: 难 / 并查集 思维】
很轻松的暴力做法骗22分
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*3+10;
int h[N],e[N],ne[N],idx;
int st[N],vis[N];
int n,m,t;
int startx,endx;
bool flag;
void add(int a,int b) {e[idx]=b,ne[idx]=h[a],h[a]=idx++;}
void dfs(int u)
{
st[u]=1;
if(u==endx&&!vis[u])
{
flag=1;
return;
}
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i];
if(!st[j]&&!vis[j]) dfs(j);
}
}
int main(void)
{
memset(h,-1,sizeof h);
cin>>n>>m>>t;
for(int i=0;i<m;i++)
{
int a,b; cin>>a>>b;
add(a,b),add(b,a);
}
while(t--)
{
int c,q; cin>>c>>q;
vis[c]=1;
int ans=q;
for(int i=0;i<q;i++)
{
memset(st,0,sizeof st);
flag=0;
cin>>startx>>endx;
if(!vis[startx])dfs(startx);
if(flag) ans--;
}
cout<<ans<<endl;
}
return 0;
}
正解: 考虑将所有操作离线,逆序处理。即,先删除要删除的所有点,再倒着往里加点,顺便把询问处理掉,用并查集维护即可
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef pair<int,int> PII;
vector<int>ve[N];//存边
vector<PII>vis[N];
int p[N],s[N],ans[N];
int n,m,t;
int find(int x)
{
if(x!=p[x]) p[x]=find(p[x]);
return p[x];
}
int main(void)
{
cin>>n>>m>>t;
for(int i=1;i<=n;i++) p[i]=i;
for(int i=1;i<=m;i++)
{
int a,b; cin>>a>>b;
ve[a].push_back(b) ;
ve[b].push_back(a);
}
for(int i=1;i<=t;i++)
{
int k,a,以上是关于2021 RoboCom 世界机器人开发者大赛-本科组(初赛)完结的主要内容,如果未能解决你的问题,请参考以下文章
2021 RoboCom 世界机器人开发者大赛-本科组(初赛)完结
2021 RoboCom 世界机器人开发者大赛-本科组(复赛)
2021 RoboCom 世界机器人开发者大赛-本科组(复赛)
2021 RoboCom 世界机器人开发者大赛-本科组(决赛)