这道题只接受 C、C++ 和 C#。 能自己定义赋值时整份数据被复制的值类型结构体(struct)的,只有这三种语言。 Python、JavaScript、TypeScript、Java 的对象和 Craykon 的 字典() 赋值时是共享同一个东西的引用,所以要做这道题的 copy 必须另外复制一份。 C、C++ 的 r[i] = r[j] 会复制所有成员,之后两台机器人各自移动。 C# 中 struct Point 同样会复制,但若是 class Point,同样的赋值只复制引用,之后移动其中一个,两个格子会一起动。 三个陷阱:① 在 C 里像 void move(Point p, int dx, int dy) 这样按值接收,只移动了副本,数组里的机器人不动;要用 Point *p 接收、调用 move(&r[i], dx, dy),在里面写 p->x += dx(C++ 用成员函数或 Point&)。 ② 在 C# 里把 struct 改成 class,copy 之后两台机器人就成了同一台。 ③ 在 C# 的 List<Point> 上写 r[i].Move(dx, dy) 能编译也不报错,但它只移动了索引器返回的副本然后丢掉。 数组 Point[] 的元素是变量,所以 r[i].Move() 会改变元素本身。 用 List 时要取出、修改、再放回(var p = r[i]; p.Move(dx, dy); r[i] = p;)。
C#Main.cs · 41 行
using System;using System.IO;using System.Text;struct Point // 값 타입: 대입하면 데이터가 복사된다{ public int X, Y; public void Move(int dx, int dy) { X += dx; Y += dy; }}class Program{ static void Main() { string[] t = Console.In.ReadToEnd().Split((char[])null, StringSplitOptions.RemoveEmptyEntries); int pos = 0; int n = int.Parse(t[pos++]); var r = new Point[n]; // 배열 칸은 변수라서 r[i].Move()가 칸 자체를 바꾼다 for (int i = 0; i < n; i++) r[i] = new Point { X = int.Parse(t[pos++]), Y = int.Parse(t[pos++]) }; int q = int.Parse(t[pos++]); for (int k = 0; k < q; k++) { string cmd = t[pos++]; int i = int.Parse(t[pos++]) - 1; if (cmd == "move") { int dx = int.Parse(t[pos++]), dy = int.Parse(t[pos++]); r[i].Move(dx, dy); } else { int j = int.Parse(t[pos++]) - 1; if (cmd == "copy") r[i] = r[j]; // 복사본이 들어가서 이후 따로 움직인다 else (r[i], r[j]) = (r[j], r[i]); } } var sb = new StringBuilder(); foreach (var p in r) sb.Append(p.X).Append(' ').Append(p.Y).Append('\n'); Console.Write(sb); }}
C++main.cpp · 38 行
#include <iostream>#include <string>#include <utility>#include <vector>struct Point { int x, y; void move(int dx, int dy) { // 멤버 함수는 자기 자신(원본)을 바꾼다 x += dx; y += dy; }};int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int n, q; std::cin >> n; std::vector<Point> r(n); for (auto& p : r) std::cin >> p.x >> p.y; std::cin >> q; std::string cmd; for (int k = 0; k < q; k++) { int i, j, dx, dy; std::cin >> cmd; if (cmd == "move") { std::cin >> i >> dx >> dy; r[i - 1].move(dx, dy); // vector의 operator[]는 참조를 돌려줘서 원본이 바뀐다 } else if (cmd == "copy") { std::cin >> i >> j; r[i - 1] = r[j - 1]; // 값 복사 } else { std::cin >> i >> j; std::swap(r[i - 1], r[j - 1]); } } for (const auto& p : r) std::cout << p.x << " " << p.y << "\n";}
Cmain.c · 39 行
#include <stdio.h>#include <string.h>typedef struct { int x, y;} Point;/* 원본을 움직이려면 포인터로 받는다 */void move(Point *p, int dx, int dy) { p->x += dx; p->y += dy;}int main(void) { static Point r[1000]; int n, q; scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d %d", &r[i].x, &r[i].y); scanf("%d", &q); char cmd[8]; for (int k = 0; k < q; k++) { int i, j, dx, dy; scanf("%7s", cmd); if (strcmp(cmd, "move") == 0) { scanf("%d %d %d", &i, &dx, &dy); move(&r[i - 1], dx, dy); } else if (strcmp(cmd, "copy") == 0) { scanf("%d %d", &i, &j); r[i - 1] = r[j - 1]; /* 구조체 대입은 멤버를 통째로 복사: 이후 둘은 따로 움직인다 */ } else { scanf("%d %d", &i, &j); Point t = r[i - 1]; r[i - 1] = r[j - 1]; r[j - 1] = t; } } for (int i = 0; i < n; i++) printf("%d %d\n", r[i].x, r[i].y); return 0;}