ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AtCoder Beginner Contest 259

2022-07-10 00:00:26  阅读:245  来源: 互联网

标签:AtCoder Beginner idx int Sample vis 259 圆上 dis


AtCoder Beginner Contest 259

https://atcoder.jp/contests/abc259

先把D放这里,其他的明天补上来

D - Circumferences

题源:abc259_d
人生中第一次做出D题于是就来发题解了

题目描述

给定n个圆(圆心坐标和半径r),以及起点和终点的坐标(这两点必在某个圆上)
已知 点可以沿着圆的边界(即在圆上移动),试判断能否从起点走到终点。

样例

Sample Input 1

4
0 -2 3 3
0 0 2
2 0 2
2 3 1
-3 3 3

Sample Output 1

Yes

Sample Input 2

3
0 1 0 3
0 0 1
0 0 2
0 0 3


Sample Output 2

No

分析

点一定是在圆上动的,所以当走到两圆交界处的时候就可以顺势走到另一个圆上。
(这里没法放图片,所以可以去原题看样例的截图来辅助来理解)
那么此时就等价于,在这两个圆之间建立一条无向边,于是问题就转化为:求 起点所在的圆 到 终点所在的圆的最短路

分析完毕,梳理一下要做的事:

  1. 找到起点和终点所在的圆的编号,记录为st和ed;
  2. 把所有两两相交的圆找到,然后建边(注意特判同心圆不可达的情况)
  3. 跑最短路的板子

Code

代码写的很潦草,轻喷
SPFA

#include <bits/stdc++.h>
#define int long long

using namespace std;
typedef pair<int, int> pii;
const int N = 3005*3005, inf = 1e18;
int h[N], ee[N], ne[N], w[N], idx;
int sx, sy, fx, fy, st = 0, ed = 0, n;
int dis[N];
bool vis[N];
//int a[N][N];

void add (int a, int b, int c) {
    ee[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++;
}

struct Node {
    int x, y, r;
    bool operator<(const Node &t)const {
        return x < t.x;
    }
}e[N];

void spfa () {
    queue<int>q;
    for (int i = 1; i <= n; i ++)   dis[i] = inf;
    dis[st] = 0;
    q.push(st);
    vis[st]  = true;
    
    while (!q.empty()) {
        int t = q.front();
        q.pop();
        vis[t] = false;
        
        for (int i = h[t]; i != -1; i = ne[i]) {
            int j = ee[i];
            if (dis[j] > dis[t]+ w[i]) {
                dis[j] = dis[t] + w[i];
                if (!vis[j])
                    q.push (j), vis[j] = true;
            }
        }
    }
    //for (int i = 1; i <= n; i ++)   cout << dis[i] << endl;
    // cout << dis[ed] << endl;

    if (dis[ed] != inf)  cout << "Yes\n";
    else    cout << "No\n";
}

signed main () {
    cin >> n;
    cin >> sx >> sy >> fx >> fy;
    for (int i = 1; i <= n; i ++) {
        int x, y, r;
        cin >> x >> y >> r;
        e[i] = {x, y, r}; 
    }
    //sort (e + 1, e + n + 1);

    for (int i = 1; i <= n; i ++) {
        if (st && ed)   break;
        int x = e[i].x, y = e[i].y, r = e[i].r;
        if ((x-sx)*(x-sx) + (y-sy)*(y-sy) == r*r)   st = i;
        if ((x-fx)*(x-fx) + (y-fy)*(y-fy) == r*r)   ed = i;
    }
    //cout << "st=" << st << ", ed=" << ed << endl;

    //建图
    memset (h, -1, sizeof h);
    for (int i = 1; i <= n; i ++) {
        int x = e[i].x, y = e[i].y, r = e[i].r;
        for (int j = i + 1; j <= n; j ++) {
            int xx = e[j].x, yy = e[j].y, rr = e[j].r;
            //if (x == xx && y == yy && r != rr)  continue;
            int d1 = (x-xx)*(x-xx) + (y-yy)*(y-yy);
            int d2 = (r+rr)*(r+rr);
            if (d1 != 0 && d1 <= d2) {
                //cout << "i=" << i << ", j=" << j << endl;
                add (i, j, 1), add (j, i, 1);
                //a[i][j] = a[j][i] = 1;
            }
        }
    }

    spfa ();
}

//走边框,看看能否走到
//z找圆的交点
//抽象建图,如果两个圆有交点的话就建立一条边

难得做出图论题...

标签:AtCoder,Beginner,idx,int,Sample,vis,259,圆上,dis
来源: https://www.cnblogs.com/CTing/p/16462299.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有