首页 > 其他分享 >Gym100959I-Robots题解

Gym100959I-Robots题解

时间:2023-03-01 15:46:38浏览次数:70  
标签:pv int 题解 机器人 Robots long num Gym100959I 移动

题意:平面直角坐标系上有 \(n\) 个机器人,每个机器人有一个上下左右之一的方向,初始所有机器人静止。在第 \(0\) 秒,你让第一个机器人开始朝它的方向移动,速度为每秒一个单位。如果一个移动的机器人碰到了一个静止的机器人,该静止机器人也开始朝它的方向移动。需要注意的是,一个移动的机器人无论是否碰到其他机器人,移动的方向和速度永远不会改变。求 \(T\) 秒后的状态。

由于一旦开始移动,后面的状态都是很简单的,所以只需要求出每个机器人从什么时候开始移动即可。考虑如下建图:若机器人 \(i\) 走 \(x\) 秒后会碰到机器人 \(j\),则连一条 \(i\xrightarrow{x}j\) 的边。则每个机器人开始移动的时间即为从 \(1\) 走到该点的最短路。

此时只剩一个问题:建图是 \(n^2\) 的。我们可以发现,当一个向上的机器人 \(i\) 撞到了一个同样向上的机器人 \(j\) 时,\(i\) 和 \(j\) 便没有本质区别了,只需要保留一个。此时有两种处理方式:舍弃 \(i\) 和舍弃 \(j\)。容易证明此时建图的边数变为了 \(O(n)\) 条。

舍弃 \(i\) 的实现:

By cxm1024

#include<bits/stdc++.h>
using namespace std;
#define int long long
struct node {
	int x,y;
	char d;
} a[100010];
map<int,set<pair<int,int> > > mx,my;
vector<pair<int,int> > e[100010];
int ans[100010];
bool done[100010];
void dijkstra(int s) {
	struct node2 {
		int u,w;
		bool operator<(const node2 &o)const {
			return w>o.w;
		}
	};
	priority_queue<node2> q;
	q.push({s,0});
	while(!q.empty()) {
		auto [u,w]=q.top();q.pop();
		if(done[u]) continue;
		done[u]=1,ans[u]=w;
		for(auto v:e[u])
			if(!done[v.first])
				q.push({v.first,w+v.second});
	}
}
signed main() {
	int n,t;
	cin>>n>>t;
	for(int i=1;i<=n;i++) {
		cin>>a[i].x>>a[i].y>>a[i].d;
		mx[a[i].x].insert({a[i].y,i});
		my[a[i].y].insert({a[i].x,i});
	}
	for(int i=1;i<=n;i++) {
		if(a[i].d=='U') {
			auto &s=mx[a[i].x];
			for(auto tmp=s.find({a[i].y,i});tmp!=s.end();tmp++) {
				if((*tmp).second==i) continue;
				e[i].push_back({(*tmp).second,(*tmp).first-a[i].y});
				if(a[(*tmp).second].d=='U') break;
			}
		}
		else if(a[i].d=='D') {
			auto &s=mx[a[i].x];
			for(auto tmp=s.find({a[i].y,i});;) {
				if((*tmp).second!=i) {
					e[i].push_back({(*tmp).second,a[i].y-(*tmp).first});
					if(a[(*tmp).second].d=='D') break;
				}
				if(tmp==s.begin()) break;
				else tmp--;
			}
		}
		else if(a[i].d=='L') {
			auto &s=my[a[i].y];
			for(auto tmp=s.find({a[i].x,i});;) {
				if((*tmp).second!=i) {
					e[i].push_back({(*tmp).second,a[i].x-(*tmp).first});
					if(a[(*tmp).second].d=='L') break;
				}
				if(tmp==s.begin()) break;
				else tmp--;
			}
		}
		else {
			auto &s=my[a[i].y];
			for(auto tmp=s.find({a[i].x,i});tmp!=s.end();tmp++) {
				if((*tmp).second==i) continue;
				e[i].push_back({(*tmp).second,(*tmp).first-a[i].x});
				if(a[(*tmp).second].d=='R') break;
			}
		}
	}
	dijkstra(1);
	for(int i=1;i<=n;i++) {
		if(!done[i]||ans[i]>t) {
			cout<<a[i].x<<" "<<a[i].y<<endl;
			continue;
		}
		int len=t-ans[i];
		if(a[i].d=='U') a[i].y+=len;
		else if(a[i].d=='D') a[i].y-=len;
		else if(a[i].d=='L') a[i].x-=len;
		else a[i].x+=len;
		cout<<a[i].x<<" "<<a[i].y<<endl;
	}
	return 0;
}

舍弃 \(j\) 的实现:

By ainta

#include<stdio.h>
#include<algorithm>
#include<queue>
#define pli pair<long long,int>
using namespace std;
vector<int>E[101000], L[101000];
struct point{
    int x, y, num, dir;
    bool operator <(const point &p)const{
        return x!=p.x?x<p.x:y<p.y;
    }
}w[101000], ori[101000];
int n;
long long T, D[101000];
priority_queue<pli>PQ;
void Ins(int a, long long d){
    if(D[a]<=d)return;
    D[a]=d;
    PQ.push(pli(-d,a));
}
void Dijk(){
    int i, a;
    for(i=1;i<=n;i++)D[i] = 2e18;
    Ins(1,0);
    pli tp;
    while(1){
        while(!PQ.empty()){
            tp = PQ.top();
            if(D[tp.second] == -tp.first)break;
            PQ.pop();
        }
        if(PQ.empty())break;
        tp = PQ.top();
        a = tp.second;
        PQ.pop();
        for(i=0;i<E[a].size();i++){
            Ins(E[a][i],D[a]+L[a][i]);
        }
    }
}
void Add(int a, int b, int c){
    E[a].push_back(b);
    L[a].push_back(c);
}
int main(){
    int i, j, e, pv, y;
    char pp[3];
    scanf("%d%lld",&n,&T);
    for(i=1;i<=n;i++){
        scanf("%d%d",&w[i].x,&w[i].y);
        scanf("%s",pp);
        if(pp[0]=='U')w[i].dir = 1;
        if(pp[0]=='D')w[i].dir = 2;
        if(pp[0]=='R')w[i].dir = 3;
        if(pp[0]=='L')w[i].dir = 4;
        w[i].num = i;
        ori[i] = w[i];
    }
    sort(w+1,w+n+1);
    for(i=1;i<=n;i++){
        for(j=i;j<=n;j++)if(w[j].x!=w[i].x)break;
        e=j-1;
        pv = 0;
        for(j=i;j<=e;j++){
            if(pv)Add(pv,w[j].num,w[j].y-y);
            if(w[j].dir == 1)pv = w[j].num, y = w[j].y;
        }
        pv = 0;
        for(j=e;j>=i;j--){
            if(pv)Add(pv,w[j].num,y-w[j].y);
            if(w[j].dir == 2)pv = w[j].num, y = w[j].y;
        }
        i=e;
    }
    for(i=1;i<=n;i++)swap(w[i].x,w[i].y);
    sort(w+1,w+n+1);
    for(i=1;i<=n;i++){
        for(j=i;j<=n;j++)if(w[j].x!=w[i].x)break;
        e=j-1;
        pv = 0;
        for(j=i;j<=e;j++){
            if(pv)Add(pv,w[j].num,w[j].y-y);
            if(w[j].dir == 3)pv = w[j].num, y = w[j].y;
        }
        pv = 0;
        for(j=e;j>=i;j--){
            if(pv)Add(pv,w[j].num,y-w[j].y);
            if(w[j].dir == 4)pv = w[j].num, y = w[j].y;
        }
        i=e;
    }
    Dijk();
    long long xx,yy;
    for(i=1;i<=n;i++){
        xx=ori[i].x,yy=ori[i].y;
        if(D[i]<=T){
            if(ori[i].dir==1)yy+=T-D[i];
            if(ori[i].dir==2)yy-=T-D[i];
            if(ori[i].dir==3)xx+=T-D[i];
            if(ori[i].dir==4)xx-=T-D[i];
        }
        printf("%lld %lld\n",xx,yy);
    }
}

标签:pv,int,题解,机器人,Robots,long,num,Gym100959I,移动
From: https://www.cnblogs.com/cxm1024/p/17168451.html

相关文章

  • Gym101252B-Kakuro题解
    题目传送门题意:有一个矩阵,每个格子为黑色或白色。你需要向白色格子中填\(1\sim9\)的整整睡。从某一个黑色格子的右侧往右连续的一段极长的白色格子被称为一个run,往下......
  • C#、IIS获取时间带星期或日期问题解决
    ,获取时间老是带星期,如:2018-8-8星期日12:00:00,造成写入数据库时无法识别为时间格式报错。试了修改区域语言和修改指定注册表均无效。   解决方法一:在代码里处理时......
  • SPOJ Query On A Tree IV 题解
    SPOJQueryOnATreeIV题解一个边分治套线段树套堆的题目比较难写但是有不小的启发思路来源和代码都抄自[SPOJ-QTREE4]QUERYONATREEIV题解|KSKUN'sBlog简......
  • [CF282D] Yet Another Number Game 题解
    [CF282D]YetAnotherNumberGame传送门这题可以分三种情况讨论\(n\)的取值。n=1显然,当\(a1\neq0\)时先手可以一下全部取完,后手必败,否则后手必胜。n=2有......
  • AtCoder Beginner Contest 275 A-F 题解
    比赛链接砳赫賏,看懂扣1(A-FindTakahashi模拟。#include<cstdio>#include<algorithm>usingnamespacestd;intn,mx,id=1;intmain(){ intx; scanf("%d......
  • Codeforces Round #854 by cybercats (Div. 1 + Div. 2) A-B题解
    比赛链接A可以发现,每次出去的顺序一定是按照\(n->1\)的顺序。因为新加入的东西只会放在最前面。相应的,如果其已在序列中,则这个操作不会对\(1~n\)的信息产生影响。......
  • border出现虚边问题解决
    当我们只给元素设置了border-top,没有设置其他边框的时候,如果我们使用了border-radius会出现虚边的情况,如下所示:css代码:div{width:100px;height:100px;border-top:2pxsoli......
  • 跨域问题解决
    目录跨域请求问题解决解决跨域问题方式简单请求与非简单请求自己编写中间件处理跨域请求问题解决同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全......
  • Codeforces Round #854 by cybercats (Div. 1+2) 1799 A~G 题解
    点我看题A.RecentActions注意到只有编号大于n的博客会被更新,所以每当有一个之前没被更新的过的博客被更新时,当前列表中最下面的就会被挤掉。如果这次更新的博客之前已......
  • [洛谷]P5401 [CTS2019] 珍珠 题解
    [洛谷]P5401[CTS2019]珍珠题解题意概述有\(D\)种珍珠,每种有无限颗,现在等概率的从\(D\)种珍珠中抽\(n\)次珍珠,每次抽\(1\)个珍珠,记第\(i\)种珍珠最后一共抽......