There are n adventurers and t teams.
Each adventurer has a position (x, y) and belongs to one team.
Each team has one vault, and all adventurers on the same team share that one vault.
The first line gives n and t, and the second line gives the starting amounts of teams 1 to t.
The next n lines give adventurers 1 to n as "x y team".
Then comes the number of commands q, followed by q lines with one command each.
- move i dx dy: adventurer i moves by dx in x and dy in y.
- earn i g: put g into the vault of adventurer i's team.
- clone i j: make adventurer i a clone of adventurer j. The position becomes j's current position, and the team becomes j's team. After that the two positions move independently, but since they are on the same team they share the vault.
- leave i: adventurer i leaves the current team and forms a new team alone, with a vault of 0. The old team's vault stays as it is, and the new team's vault is 0 even if i was alone on the old team.
i and j may be equal (then clone changes nothing).
After carrying out the commands in order, print "x y vault_amount" for adventurers 1 to n, one per line. The vault amount is the amount in the vault of that adventurer's team.
Try modeling an adventurer as a struct whose members are a position struct (a value) and something that points to the team (a C pointer, a C++ shared_ptr, a C# class reference), and doing clone with a single struct assignment.
Input
1 ≤ n ≤ 1,000, 1 ≤ t ≤ 1,000, 1 ≤ q ≤ 10,000. Starting amounts are integers from 0 to 1,000,000, g from 1 to 1,000, and starting coordinates and dx, dy from -1,000 to 1,000. 1 ≤ team ≤ t, 1 ≤ i, j ≤ n
When you run, these lines are fed to input()/stdin in order (the program doesn't stop to ask).
$ Ready
Open this on a computer to write and run code. On mobile you can read the problem and the solutions.
In other languagesShow solutions by language · 3 languages
This problem accepts only C, C++ and C#. Those three let a value-type struct, copied whole on assignment, also hold a member that points to something else. Objects in Python, JavaScript, TypeScript and Java, and Craykon's Dict(), are all references, so a single assignment cannot split 'copy the position, share the team'. The key point is that struct assignment is a shallow copy. Value members (the position) are copied anew, while pointing members copy only the address (reference) and so point to the same thing. That role is played by Team *team in C, std::shared_ptr<Team> team in C++ (copies point to the same Team, which is deleted when the last one goes away), and a class Team field inside struct Adventurer in C#. Five traps: ① In C#, making Point a class makes the two adventurers share one position after clone, so when one moves both move. ② In C#, making Team a struct copies the vault on clone, so money put in afterwards goes to only one side. ③ In C#, making Adventurer a class makes a[i] = a[j] turn the two slots into one object. ④ In C and C++, holding the team by value as Team team; gives even adventurers who start on the same team separate vaults. ⑤ In C++, taking Adventurer me = a[i - 1]; changes only a copy. Take Adventurer &me. In C# too, with a List<Adventurer>, list[i].Pos.X += dx is a compile error (CS1612), so use an array Adventurer[], whose slots are variables.
C#Main.cs · 67 lines
using System;using System.Text;struct Point // 값 형식: 대입하면 X, Y가 복사된다{ public int X, Y;}class Team // 참조 형식: 대입하면 같은 금고를 함께 가리킨다{ public int Gold;}struct Adventurer // 값 형식 안에 값(Pos)과 참조(Team)가 함께 있다{ public Point Pos; public Team Team;}class Program{ static void Main() { var tokens = Console.In.ReadToEnd().Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries); int p = 0; int Next() => int.Parse(tokens[p++]); int n = Next(), t = Next(); var teams = new Team[t]; for (int k = 0; k < t; k++) teams[k] = new Team { Gold = Next() }; var a = new Adventurer[n]; // List<Adventurer>가 아니라 배열: a[i].Pos.X += dx가 칸 자체를 바꾼다 for (int i = 0; i < n; i++) { a[i].Pos.X = Next(); a[i].Pos.Y = Next(); a[i].Team = teams[Next() - 1]; } int q = Next(); for (int c = 0; c < q; c++) { string cmd = tokens[p++]; int i = Next() - 1; switch (cmd) { case "move": a[i].Pos.X += Next(); a[i].Pos.Y += Next(); break; case "earn": a[i].Team.Gold += Next(); break; case "clone": a[i] = a[Next() - 1]; // Pos는 복사되고, Team은 참조만 복사된다 break; default: // leave a[i].Team = new Team(); break; } } var sb = new StringBuilder(); foreach (var ad in a) sb.Append($"{ad.Pos.X} {ad.Pos.Y} {ad.Team.Gold}\n"); Console.Write(sb); }}
C++main.cpp · 60 lines
#include <iostream>#include <memory>#include <string>#include <vector>struct Point { // 값: 대입하면 복사된다 int x = 0, y = 0;};struct Team { int gold = 0;};// 모험가는 좌표를 직접 담고(값), 팀은 shared_ptr로 함께 가리킨다struct Adventurer { Point pos; std::shared_ptr<Team> team;};int main() { std::ios::sync_with_stdio(false); int n, t; std::cin >> n >> t; std::vector<std::shared_ptr<Team>> teams(t); for (auto &tm : teams) { tm = std::make_shared<Team>(); std::cin >> tm->gold; } std::vector<Adventurer> a(n); for (auto &ad : a) { int k; std::cin >> ad.pos.x >> ad.pos.y >> k; ad.team = teams[k - 1]; } int q; std::cin >> q; for (int c = 0; c < q; c++) { std::string cmd; int i; std::cin >> cmd >> i; Adventurer &me = a[i - 1]; // 참조로 받아야 배열의 모험가가 바뀐다 if (cmd == "move") { int dx, dy; std::cin >> dx >> dy; me.pos.x += dx; me.pos.y += dy; } else if (cmd == "earn") { int g; std::cin >> g; me.team->gold += g; } else if (cmd == "clone") { int j; std::cin >> j; me = a[j - 1]; // pos는 복사, shared_ptr는 같은 Team을 함께 가리키게 복사 } else { me.team = std::make_shared<Team>(); // 새 팀(금고 0) } } for (const auto &ad : a) std::cout << ad.pos.x << ' ' << ad.pos.y << ' ' << ad.team->gold << '\n';}
Cmain.c · 59 lines
#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct { int x, y; } Point; /* 값: 대입하면 복사된다 */typedef struct { int gold; } Team;/* 모험가는 좌표를 직접 담고(값), 팀은 주소로 가리킨다(같은 팀이면 같은 주소) */typedef struct { Point pos; Team *team;} Adventurer;int main(void) { int n, t, q; scanf("%d %d", &n, &t); /* 팀 자리: 처음 t개 + leave 때마다 하나씩(많아야 q개) */ int cap = t + 10000; Team *teams = malloc((size_t)cap * sizeof *teams); int used = t; for (int k = 0; k < t; k++) scanf("%d", &teams[k].gold); Adventurer *a = malloc((size_t)n * sizeof *a); for (int i = 0; i < n; i++) { int k; scanf("%d %d %d", &a[i].pos.x, &a[i].pos.y, &k); a[i].team = &teams[k - 1]; } scanf("%d", &q); for (int c = 0; c < q; c++) { char cmd[8]; int i; scanf("%7s %d", cmd, &i); Adventurer *me = &a[i - 1]; if (strcmp(cmd, "move") == 0) { int dx, dy; scanf("%d %d", &dx, &dy); me->pos.x += dx; me->pos.y += dy; } else if (strcmp(cmd, "earn") == 0) { int g; scanf("%d", &g); me->team->gold += g; /* 같은 팀 모두가 보는 금고 */ } else if (strcmp(cmd, "clone") == 0) { int j; scanf("%d", &j); *me = a[j - 1]; /* 구조체 대입: pos는 복사, team은 주소만 복사 */ } else { /* leave: 새 팀을 만들어 옮긴다 */ teams[used].gold = 0; me->team = &teams[used++]; } } for (int i = 0; i < n; i++) printf("%d %d %d\n", a[i].pos.x, a[i].pos.y, a[i].team->gold); free(a); free(teams); return 0;}