巨人和鬼题解

题目描述

洛谷链接: https://www.luogu.com.cn/problem/U214788
更好的阅读体验: https://qiu-weidong.github.io/2022/04/08/giants-and-ghosts/
n n n个巨人和 n n n个鬼正在战斗。每个巨人都配备了质子炮,可以发射质子流来消灭鬼。质子流沿直线行进,击中鬼之后就会消失。
由于质子流威力巨大,一旦两束质子流发生碰撞,后果不堪设想。因此,巨人必须谨慎地选择鬼作为射击目标,以便保证质子流不会发生碰撞。
已知巨人和鬼的坐标没有三者是共线的,求可行的射击方案。

输入

第一行一个正整数 n n n,表示巨人和鬼的个数。
接下来 n n n行,每行三个数,第一个数表示该巨人的 i d id id,后两个是浮点数,分别表示该巨人的 x x x坐标和 y y y坐标。
接下来 n n n行,每行三个数,分别表示鬼的 i d id id,鬼的 x x x坐标和 y y y坐标。

输出

输出 n n n行,每行两个整数 g i a n t i giant_i gianti g h o s t i ghost_i ghosti,表示 i d id id g i a n t i giant_i gianti的巨人的射击目标是 i d id id g h o s t i ghost_i ghosti的鬼。

样例

输入

2
0 0.00 0.00
1 1.00 0.00
0 0.00 1.00
1 2.00 2.00

输出

0 0
1 1

数据范围

n ≤ 2100 n \leq 2100 n2100

具体实现

C++实现

#include <vector>
#include <iostream>
#include <algorithm>
#include <cassert>

using std::pair;
using std::vector;

struct giant_ghost
{
    double x;
    double y;
    bool is_giant;
    int id;
};

vector<giant_ghost> giants_ghosts;
vector<pair<int, int>> ans;

void giants_and_ghosts(int l, int r)
{
    if (l > r)
        return;
    assert((r - l) % 2 != 0);
    if (r - l == 1)
    {
        assert(giants_ghosts[l].is_giant || giants_ghosts[r].is_giant);
        assert(!(giants_ghosts[l].is_giant && giants_ghosts[r].is_giant));
        if (giants_ghosts[l].is_giant)
        {
            ans.push_back(std::make_pair(giants_ghosts[l].id, giants_ghosts[r].id));
        }
        else
        {
            ans.push_back(std::make_pair(giants_ghosts[r].id, giants_ghosts[l].id));
        }
        return;
    }

    int index = l;
    giant_ghost left = giants_ghosts[l];

    for (int i = l + 1; i <= r; i++)
    {
        if (giants_ghosts[i].y < left.y || giants_ghosts[i].y == left.y && giants_ghosts[i].x < left.x)
        {
            index = i;
            left = giants_ghosts[i];
        }
    }

    left = giants_ghosts[l];
    giants_ghosts[l] = giants_ghosts[index];
    giants_ghosts[index] = left;
    left = giants_ghosts[l];

    std::sort(giants_ghosts.begin() + 1 + l, giants_ghosts.begin() + 1 + r, [&left](const giant_ghost &g1, const giant_ghost &g2)
              {
        double x1 = g1.x - left.x;
        double y1 = g1.y - left.y;

        double x2 = g2.x - left.x;
        double y2 = g2.y - left.y;
        // (1, 0) x (0, 1) = 1
        return x1 * y2 - x2 * y1 > 0; });

    int giant_cnt = left.is_giant ? 1 : 0;
    int ghost_cnt = left.is_giant ? 0 : 1;
    index = l;

    do
    {
        index++;
        assert(index <= r);
        if(giants_ghosts[index].is_giant) giant_cnt++;
        else ghost_cnt++;
    } while (giant_cnt != ghost_cnt);

    // l和index匹配
    if(giants_ghosts[l].is_giant) ans.push_back(std::make_pair(giants_ghosts[l].id, giants_ghosts[index].id));
    else ans.push_back(std::make_pair(giants_ghosts[index].id, giants_ghosts[l].id));

    giants_and_ghosts(l+1, index-1);
    giants_and_ghosts(index+1, r);
}

int main(int argc, const char **argv)
{
    int n;
    std::cin >> n;

    for (int _ = 0; _ < n; _++)
    {
        giant_ghost tp;
        std::cin >> tp.id >> tp.x >> tp.y;
        tp.is_giant = true;
        giants_ghosts.push_back(tp);
    }

    for (int _ = 0; _ < n; _++)
    {
        giant_ghost tp;
        std::cin >> tp.id >> tp.x >> tp.y;
        tp.is_giant = false;
        giants_ghosts.push_back(tp);
    }

    giants_and_ghosts(0, giants_ghosts.size()-1);

    for(const auto & pair : ans) {
        std::cout << pair.first << " " << pair.second << std::endl;
    }
}

rust实现

#[derive(Clone, Copy)]
struct GiantGhost {
    x : f64,
    y : f64,
    is_giant: bool,
    id: i32
}

fn giants_and_ghosts(giants_ghosts : &mut [GiantGhost]) {
    if giants_ghosts.len() <= 0 {
        return;
    }

    assert_eq!(giants_ghosts.len() % 2, 0);
    if giants_ghosts.len() == 2 {
        assert!(giants_ghosts[0].is_giant || giants_ghosts[1].is_giant);
        assert!(!(giants_ghosts[0].is_giant && giants_ghosts[1].is_giant));


        if giants_ghosts[0].is_giant {
            println!("{} {}", giants_ghosts[0].id, giants_ghosts[1].id);
        }
        else {
            println!("{} {}", giants_ghosts[1].id, giants_ghosts[0].id);
        }
        return;
    }

    let mut index = 0;
    let mut left = giants_ghosts[0];

    for i in 1..giants_ghosts.len() {
        if giants_ghosts[i].y < left.y || giants_ghosts[i].y == left.y && giants_ghosts[i].x < left.x {
            index = i;
            left = giants_ghosts[i];
        }
    }

    left = giants_ghosts[0];
    giants_ghosts[0] = giants_ghosts[index];
    giants_ghosts[index] = left;
    left = giants_ghosts[0];

    let slice = &mut giants_ghosts[1..];
    slice.sort_by(|g1, g2| {
        let x1 = g1.x - g2.x;
        let y1 = g1.y - g2.y;
        let x2 = g2.x - left.x;
        let y2 = g2.y - left.y;

        let ans = x1 * y2 - x2 * y1;
        if ans == 0.0 {
            return std::cmp::Ordering::Equal;
        }
        else if ans > 0.0 {
            return std::cmp::Ordering::Less;
        }
        else {
            return std::cmp::Ordering::Greater;
        }
    });

    let mut giant_cnt = if left.is_giant { 1 } else { 0 };
    let mut ghost_cnt = if left.is_giant { 0 } else { 1 };
    index = 0;

    loop {
        index += 1;
        assert!(index < giants_ghosts.len());
        if giants_ghosts[index].is_giant { giant_cnt += 1; }
        else { ghost_cnt += 1; }

        if giant_cnt == ghost_cnt { break; }
    } 


    if giants_ghosts[0].is_giant {
        println!("{} {}", giants_ghosts[0].id, giants_ghosts[index].id);
    }
    else {
        println!("{} {}", giants_ghosts[index].id, giants_ghosts[0].id);
    }

    if 1 < index-1 {
        giants_and_ghosts(&mut giants_ghosts[1..index]);
    }
    if index + 1 < giants_ghosts.len() {
        giants_and_ghosts(&mut giants_ghosts[(index+1)..]);
    }
}
fn main() {
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).unwrap();
    let n : i32 = input.trim().parse().unwrap();

    let mut giants_ghosts : Vec<GiantGhost> = Vec::new();
    for _ in 0..n {
        input.clear();
        std::io::stdin().read_line(&mut input).unwrap();
        while input.trim().len() <= 0 {
            std::io::stdin().read_line(&mut input).unwrap();
        }
        let mut s = input.trim().split(' ');
        let id : i32 = s.next().unwrap().trim().parse().unwrap();
        let x : f64 = s.next().unwrap().trim().parse().unwrap();
        let y : f64 = s.next().unwrap().trim().parse().unwrap();
        

        giants_ghosts.push(GiantGhost {x, y,is_giant:true, id});
    }

    for _ in 0..n {
        input.clear();
        std::io::stdin().read_line(&mut input).unwrap();
        while input.trim().len() <= 0 {
            std::io::stdin().read_line(&mut input).unwrap();
        }
        let mut s = input.trim().split(' ');

        let id : i32 = s.next().unwrap().trim().parse().unwrap();
        let x : f64 = s.next().unwrap().trim().parse().unwrap();
        let y : f64 = s.next().unwrap().trim().parse().unwrap();
        

        giants_ghosts.push(GiantGhost {x, y,is_giant:false, id});
    }

    giants_and_ghosts(&mut giants_ghosts[..]);
    // println!("hello world! {}", input)
    // let x = &giants_ghosts[1..1];
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
06-01
这道题是一道典型的费用限制最短路题目,可以使用 Dijkstra 算法或者 SPFA 算法来解决。 具体思路如下: 1. 首先,我们需要读入输入数据。输入数据中包含了道路的数量、起点和终点,以及每条道路的起点、终点、长度和限制费用。 2. 接着,我们需要使用邻接表或邻接矩阵来存储图的信息。对于每条道路,我们可以将其起点和终点作为一个有向边的起点和终点,长度作为边权,限制费用作为边权的上界。 3. 然后,我们可以使用 Dijkstra 算法或 SPFA 算法求解从起点到终点的最短路径。在这个过程中,我们需要记录到每个点的最小费用和最小长度,以及更新每条边的最小费用和最小长度。 4. 最后,我们输出从起点到终点的最短路径长度即可。 需要注意的是,在使用 Dijkstra 算法或 SPFA 算法时,需要对每个点的最小费用和最小长度进行松弛操作。具体来说,当我们从一个点 u 经过一条边 (u,v) 到达另一个点 v 时,如果新的费用和长度比原来的小,则需要更新到达 v 的最小费用和最小长度,并将 v 加入到优先队列(Dijkstra 算法)或队列(SPFA 算法)中。 此外,还需要注意处理边权为 0 或负数的情况,以及处理无法到达终点的情况。 代码实现可以参考以下样例代码: ```c++ #include <cstdio> #include <cstring> #include <queue> #include <vector> using namespace std; const int MAXN = 1005, MAXM = 20005, INF = 0x3f3f3f3f; int n, m, s, t, cnt; int head[MAXN], dis[MAXN], vis[MAXN]; struct Edge { int v, w, c, nxt; } e[MAXM]; void addEdge(int u, int v, int w, int c) { e[++cnt].v = v, e[cnt].w = w, e[cnt].c = c, e[cnt].nxt = head[u], head[u] = cnt; } void dijkstra() { priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q; memset(dis, 0x3f, sizeof(dis)); memset(vis, 0, sizeof(vis)); dis[s] = 0; q.push(make_pair(0, s)); while (!q.empty()) { int u = q.top().second; q.pop(); if (vis[u]) continue; vis[u] = 1; for (int i = head[u]; i != -1; i = e[i].nxt) { int v = e[i].v, w = e[i].w, c = e[i].c; if (dis[u] + w < dis[v] && c >= dis[u] + w) { dis[v] = dis[u] + w; q.push(make_pair(dis[v], v)); } } } } int main() { memset(head, -1, sizeof(head)); scanf("%d %d %d %d", &n, &m, &s, &t); for (int i = 1; i <= m; i++) { int u, v, w, c; scanf("%d %d %d %d", &u, &v, &w, &c); addEdge(u, v, w, c); addEdge(v, u, w, c); } dijkstra(); if (dis[t] == INF) printf("-1\n"); else printf("%d\n", dis[t]); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值