gym100959I Robots 2015-2016 Petrozavodsk Winter Training Camp, Makoto rng_58 Soejima Сontest 4

该博客介绍了一种解决机器人激活问题的方法,通过记录每个机器人可激活的最近机器人,并构建网格图进行最短路径计算。文章详细阐述了如何预处理数据,构建边并进行最短路搜索,最后输出机器人的新位置。内容涉及图论和算法优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://codeforces.com/gym/100959/

对于每个机器人,我们都只记录上下左右可以激活它的最近的机器人是哪个,然后从那个连到他一条边,然后跑最短路就行了

因为只能走直的,所以相当于是个网格图,那么对于一个可激活别人的机器人,如果i能激活j,j能激活k,i也能激活k的话,那么就只需要连i->j->k,没必要连i->k了,那么总边数最多4n

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
 
const int maxl=1e5+10;
 
int n,m,cas,totx,toty;ll ans,T;
int xb[maxl],yb[maxl];
ll dis[maxl];
struct bot
{
  int x,y,dir,id;
}a[maxl];
vector<bot> xa[maxl],ya[maxl];
struct ed{int v,l;};
vector<ed>e[maxl];
char s[2];
typedef pair<ll,int> p;
priority_queue<p,vector<p>,greater<p> >q;
 
inline bool cmpx(const bot &a,const bot &b){return a.x<b.x;}
inline bool cmpy(const bot &a,const bot &b){return a.y<b.y;}
 
inline int findid(int b[],int tot,int x)
{
  return lower_bound(b+1,b+1+tot,x)-b;
}
 
inline void add(int u,int v,int l){e[u].push_back(ed{v,l});}
 
inline void prework()
{
  scanf("%d%lld",&n,&T);
  for(int i=1;i<=n;i++)
    {
      scanf("%d%d",&a[i].x,&a[i].y);a[i].id=i;
      xb[i]=a[i].x;yb[i]=a[i].y;
      scanf("%s",s);
      if(s[0]=='U') a[i].dir=1;
      else if(s[0]=='D') a[i].dir=2;
      else if(s[0]=='L') a[i].dir=3;
      else if(s[0]=='R') a[i].dir=4;
    }
  sort(xb+1,xb+1+n);totx=unique(xb+1,xb+1+n)-xb-1;
  sort(yb+1,yb+1+n);toty=unique(yb+1,yb+1+n)-yb-1;
  for(int i=1;i<=n;i++)
    {
      xa[findid(xb,totx,a[i].x)].push_back(a[i]);
      ya[findid(yb,toty,a[i].y)].push_back(a[i]);
    }
  for(int i=1;i<=totx;i++)
    { 
      sort(xa[i].begin(),xa[i].end(),cmpy);
      int l=xa[i].size(),lastu=0,lastuid=0,lastd=0,lastdid=0;
      for(int j=0;j<l;j++)
        {
	  if(lastuid>0)
	    add(lastuid,xa[i][j].id,xa[i][j].y-lastu);
	  if(xa[i][j].dir==1)
	    lastuid=xa[i][j].id,lastu=xa[i][j].y;
	}
      for(int j=l-1;j>=0;j--)
	{
	  if(lastdid>0)
	    add(lastdid,xa[i][j].id,lastd-xa[i][j].y);
	  if(xa[i][j].dir==2)
	    lastdid=xa[i][j].id,lastd=xa[i][j].y;
	}
    }
  for(int i=1;i<=toty;i++)
    {
      sort(ya[i].begin(),ya[i].end(),cmpx);
      int l=ya[i].size(),lastr=0,lastrid=0,lastl=0,lastlid=0;
      for(int j=0;j<l;j++)
	{
	  if(lastrid>0)
	    add(lastrid,ya[i][j].id,ya[i][j].x-lastr);
	  if(ya[i][j].dir==4)
	    lastrid=ya[i][j].id,lastr=ya[i][j].x;
	}
      for(int j=l-1;j>=0;j--)
	{
	  if(lastlid>0)
	    add(lastlid,ya[i][j].id,lastl-ya[i][j].x);
	  if(ya[i][j].dir==3)
	    lastlid=ya[i][j].id,lastl=ya[i][j].x;
	}
    }
}
 
inline void mainwork()
{
  memset(dis,0x3f,sizeof(dis));
  dis[1]=0;q.push({dis[1],1});
  while(!q.empty())
    {
      p d=q.top();q.pop();
      int u=d.second;
      if(d.first!=dis[u])
	continue;
      for(ed ee:e[u])
	{
	  int v=ee.v;
	  if(dis[v]>dis[u]+ee.l)
	    {
	      dis[v]=dis[u]+ee.l;
	      q.push({dis[v],v});
	    }
	}
    }
}
 
inline void print()
{
  for(int i=1;i<=n;i++)
    {
      ll x=a[i].x,y=a[i].y;
      if(dis[i]!=dis[0])
	{
	  if(T>dis[i])
	    {
	      if(a[i].dir==1) y+=T-dis[i];
	      if(a[i].dir==2) y-=T-dis[i];
	      if(a[i].dir==3) x-=T-dis[i];
	      if(a[i].dir==4) x+=T-dis[i];
	    }
	}
      printf("%lld %lld\n",x,y);
    }
}
 
int main()
{
  prework();
  mainwork();
  print();
  return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值