11.5 แบบฝึกหัด
เขียนแต่ละข้อเป็นไฟล์ใหม่ใน Code::Blocks รันแล้วเทียบกับผลลัพธ์ที่ต้องได้ให้ตรงทุกตัวอักษร รวมถึงช่องว่างและการขึ้นบรรทัด ติดจริงๆ ค่อยเปิดคำใบ้ และเปิดเฉลยหลังทำเสร็จแล้วเท่านั้น
ข้อ 1 ใครได้รางวัล
ห้องเรียนมีนักเรียน N คน แต่ละคนมีชื่อและคะแนนสอบปลายภาค ครูจะมอบรางวัลให้คนที่ได้คะแนนสูงสุด ถ้ามีหลายคนได้คะแนนสูงสุดเท่ากัน รางวัลเป็นของคนที่ส่งข้อสอบก่อน ซึ่งก็คือคนที่อยู่ก่อนในข้อมูลเข้า ส่วนคนอื่นที่ได้คะแนนเท่ากันจะได้เกียรติบัตร ให้หาว่าใครได้รางวัล และมีนักเรียนกี่คนที่ได้คะแนนสูงสุด
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N โดยที่ 1 ≤ N ≤ 1000
อีก N บรรทัด แต่ละบรรทัดมีชื่อของนักเรียนหนึ่งคน และคะแนน S คั่นด้วยช่องว่าง ชื่อเป็นตัวอักษรภาษาอังกฤษยาว 1 ถึง 20 ตัว ไม่มีช่องว่าง และ 0 ≤ S ≤ 100 ชื่ออาจซ้ำกันได้
ข้อมูลออก
บรรทัดแรกพิมพ์ชื่อและคะแนนของคนที่ได้รางวัล คั่นด้วยช่องว่าง บรรทัดที่สองพิมพ์จำนวนนักเรียนที่ได้คะแนนสูงสุด รวมคนที่ได้รางวัลด้วย
5
Mali 87
Krit 92
Ploy 78
Nat 92
Beam 65Krit 92
23
Somchai 45
Kanya 60
Somsak 59Kanya 60
1ดูคำใบ้
เก็บนักเรียนเป็นอาเรย์ของ struct แล้วหาคนคะแนนสูงสุดด้วยการจำ index ตามหน้า 11.2 ใช้ > ไม่ใช่ >= เพื่อให้ได้คนที่มาก่อน จากนั้นวนอีกรอบนับว่ามีกี่คนที่คะแนนเท่ากับคนนั้น
ดูเฉลย
#include <stdio.h>
typedef struct {
char name[21];
int score;
} Student;
Student students[1000];
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%s %d", students[i].name, &students[i].score);
}
int best = 0;
for (int i = 1; i < n; i++) {
if (students[i].score > students[best].score) {
best = i;
}
}
int count = 0;
for (int i = 0; i < n; i++) {
if (students[i].score == students[best].score) {
count++;
}
}
printf("%s %d\n", students[best].name, students[best].score);
printf("%d\n", count);
return 0;
}ข้อ 2 ลูกบอลในสนาม
สนามฟุตซอลเป็นสี่เหลี่ยมผืนผ้าที่ด้านขนานกับแกน x และแกน y มุมซ้ายล่างอยู่ที่ (X1, Y1) มุมขวาบนอยู่ที่ (X2, Y2) หลังซ้อมเสร็จมีลูกบอลกระจายอยู่ N ลูก ลูกที่ i อยู่ที่ (x, y) โค้ชอยากรู้ว่ามีลูกบอลอยู่ในสนามกี่ลูก อยู่บนเส้นขอบสนามพอดีกี่ลูก และอยู่นอกสนามกี่ลูก ลูกบอลถือเป็นจุดหนึ่งจุด
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม X1 Y1 X2 Y2 คั่นด้วยช่องว่าง โดยที่ X1 < X2 และ Y1 < Y2
บรรทัดที่สองมีจำนวนเต็ม N โดยที่ 1 ≤ N ≤ 1000
อีก N บรรทัด แต่ละบรรทัดมีจำนวนเต็ม x และ y ของลูกบอลหนึ่งลูก
พิกัดทุกตัวอยู่ระหว่าง -10000 ถึง 10000
ข้อมูลออก
บรรทัดเดียว มีจำนวนลูกที่อยู่ในสนาม จำนวนลูกที่อยู่บนเส้นขอบ และจำนวนลูกที่อยู่นอกสนาม คั่นด้วยช่องว่าง
0 0 10 6
6
3 2
10 4
12 3
0 0
5 6
7 71 3 2-5 -3 5 3
3
0 0
-5 3
6 01 1 1ดูคำใบ้
เก็บสนามเป็น Rect ที่มี Point สองมุมตามหน้า 11.3 แล้วเขียนฟังก์ชันรับสนามกับลูกบอลหนึ่งลูก คืนค่าว่าอยู่ข้างใน บนเส้น หรือข้างนอก ตรวจข้างนอกก่อน ถ้าไม่อยู่ข้างนอก แล้วพิกัดตัวใดตัวหนึ่งตรงกับขอบ ก็คือบนเส้น ระวังลูกที่ x ตรงกับเส้นข้างแต่ y สูงเกินสนาม ลูกนั้นอยู่ข้างนอก
ดูเฉลย
#include <stdio.h>
typedef struct {
int x;
int y;
} Point;
typedef struct {
Point low;
Point high;
} Rect;
int where(Rect field, Point ball)
{
if (ball.x < field.low.x || ball.x > field.high.x || ball.y < field.low.y || ball.y > field.high.y) {
return 2;
}
if (ball.x == field.low.x || ball.x == field.high.x || ball.y == field.low.y || ball.y == field.high.y) {
return 1;
}
return 0;
}
int main()
{
Rect field;
scanf("%d %d %d %d", &field.low.x, &field.low.y, &field.high.x, &field.high.y);
int n;
scanf("%d", &n);
int count[3] = {0, 0, 0};
for (int i = 0; i < n; i++) {
Point ball;
scanf("%d %d", &ball.x, &ball.y);
count[where(field, ball)]++;
}
printf("%d %d %d\n", count[0], count[1], count[2]);
return 0;
}ข้อ 3 ร้านที่ใกล้บ้านที่สุด
บ้านของน้องอยู่ที่พิกัด (X, Y) รอบบ้านมีร้านสะดวกซื้อ N ร้าน แต่ละร้านมีชื่อและพิกัดของตัวเอง น้องอยากรู้ว่าร้านไหนอยู่ใกล้บ้านที่สุด เมื่อวัดระยะเป็นเส้นตรง ถ้ามีหลายร้านใกล้เท่ากัน ให้ตอบร้านที่อยู่ก่อนในข้อมูลเข้า
เพื่อไม่ต้องพิมพ์ทศนิยม ให้ตอบ กำลังสองของระยะทาง แทนระยะทาง ระหว่างจุด (x1, y1) กับ (x2, y2) คือ (x1 - x2)2 + (y1 - y2)2
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม X Y คั่นด้วยช่องว่าง
บรรทัดที่สองมีจำนวนเต็ม N โดยที่ 1 ≤ N ≤ 1000
อีก N บรรทัด แต่ละบรรทัดมีชื่อร้าน และพิกัด x y ของร้าน คั่นด้วยช่องว่าง ชื่อร้านเป็นตัวอักษรภาษาอังกฤษหรือตัวเลขยาว 1 ถึง 20 ตัว ไม่มีช่องว่าง
พิกัดทุกตัวอยู่ระหว่าง -109 ถึง 109 ร้านอาจอยู่ที่เดียวกับบ้าน หรือที่เดียวกับร้านอื่นก็ได้
ข้อมูลออก
บรรทัดเดียว มีชื่อร้านที่ใกล้ที่สุด และกำลังสองของระยะทางจากบ้านถึงร้านนั้น คั่นด้วยช่องว่าง
2 3
3
SevenA 7 3
Lotus -1 6
Mart24 4 -2Lotus 180 0
3
North 0 5
East 5 0
Corner 3 4North 25ดูคำใบ้
เทียบระยะทางด้วยกำลังสองของระยะทางแบบตัวอย่าง typedef ในหน้า 11.1 ไม่ต้องถอดราก เพราะระยะที่น้อยกว่าก็มีกำลังสองน้อยกว่าเสมอ พิกัดไกลกันได้ถึง 2 × 109 ซึ่งแค่ผลต่างก็เกือบเต็ม int แล้ว และกำลังสองใหญ่ถึง 8 × 1018 ให้เก็บพิกัดใน struct เป็น long long ตั้งแต่แรก
ดูเฉลย
#include <stdio.h>
typedef struct {
long long x;
long long y;
} Point;
typedef struct {
char name[21];
Point place;
} Shop;
Shop shops[1000];
long long distance_squared(Point a, Point b)
{
long long dx = a.x - b.x;
long long dy = a.y - b.y;
return dx * dx + dy * dy;
}
int main()
{
Point home;
scanf("%lld %lld", &home.x, &home.y);
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%s %lld %lld", shops[i].name, &shops[i].place.x, &shops[i].place.y);
}
int best = 0;
long long best_distance = distance_squared(home, shops[0].place);
for (int i = 1; i < n; i++) {
long long d = distance_squared(home, shops[i].place);
if (d < best_distance) {
best = i;
best_distance = d;
}
}
printf("%s %lld\n", shops[best].name, best_distance);
return 0;
}ข้อ 4 นักวิ่งที่เร็วที่สุด
งานวิ่งการกุศลปล่อยตัวนักวิ่งเป็นกลุ่ม กลุ่มละเวลาไม่เท่ากัน เพื่อไม่ให้แออัดที่จุดเริ่ม ชิปที่ข้อเท้าของนักวิ่งแต่ละคนบันทึกเวลาออกตัวและเวลาเข้าเส้นชัยเป็นชั่วโมง นาที วินาที ผู้ชนะคือคนที่ ใช้เวลาวิ่งน้อยที่สุด ไม่ใช่คนที่เข้าเส้นก่อน ถ้ามีหลายคนใช้เวลาเท่ากัน ให้คนที่เข้าเส้นชัยก่อนชนะ ถ้ายังเท่ากันอีก ให้คนที่อยู่ก่อนในข้อมูลเข้าชนะ
ให้หาว่าใครชนะ และใช้เวลาวิ่งเท่าไร
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N โดยที่ 1 ≤ N ≤ 1000
อีก N บรรทัด แต่ละบรรทัดมีชื่อนักวิ่ง ตามด้วยจำนวนเต็มหกตัว คือชั่วโมง นาที วินาที ของเวลาออกตัว แล้วตามด้วยชั่วโมง นาที วินาที ของเวลาเข้าเส้นชัย ทุกอย่างคั่นด้วยช่องว่าง ชื่อเป็นตัวอักษรภาษาอังกฤษยาว 1 ถึง 20 ตัว ชั่วโมงอยู่ระหว่าง 0 ถึง 23 นาทีและวินาทีอยู่ระหว่าง 0 ถึง 59 ทุกคนวิ่งจบในวันเดียวกัน และเวลาเข้าเส้นชัยมาหลังเวลาออกตัวเสมอ
ข้อมูลออก
บรรทัดเดียว มีชื่อผู้ชนะ ตามด้วยเวลาที่ใช้เป็นชั่วโมง นาที และวินาที คั่นด้วยช่องว่าง นาทีและวินาทีต้องอยู่ระหว่าง 0 ถึง 59
3
Mali 6 0 0 6 50 0
Krit 6 30 0 7 15 0
Ploy 6 15 0 7 3 20Krit 0 45 02
Nat 7 10 0 9 0 20
Beam 7 0 0 8 50 20Beam 1 50 20ดูคำใบ้
เก็บนักวิ่งเป็น struct ที่มีชื่อและ Time สองตัว แล้วใช้ to_seconds กับ from_seconds แบบหน้า 11.4 คนที่ชนะคือคนที่ใช้เวลาน้อยกว่า ถ้าใช้เวลาเท่ากันให้ดูว่าใครเข้าเส้นก่อน ซึ่งก็เทียบเวลาเข้าเส้นเป็นวินาทีได้เหมือนกัน ถ้าเท่ากันทั้งสองอย่าง ใช้ < ไม่ใช่ <= เพื่อให้ได้คนที่มาก่อน
ดูเฉลย
#include <stdio.h>
typedef struct {
int hours;
int minutes;
int seconds;
} Time;
typedef struct {
char name[21];
Time start;
Time finish;
} Runner;
Runner runners[1000];
int to_seconds(Time t)
{
return t.hours * 3600 + t.minutes * 60 + t.seconds;
}
Time from_seconds(int total)
{
Time t;
t.hours = total / 3600;
t.minutes = total % 3600 / 60;
t.seconds = total % 60;
return t;
}
int used(const Runner *r)
{
return to_seconds(r->finish) - to_seconds(r->start);
}
int faster(const Runner *a, const Runner *b)
{
if (used(a) != used(b)) {
return used(a) < used(b);
}
return to_seconds(a->finish) < to_seconds(b->finish);
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
Runner *r = &runners[i];
scanf("%s %d %d %d %d %d %d", r->name,
&r->start.hours, &r->start.minutes, &r->start.seconds,
&r->finish.hours, &r->finish.minutes, &r->finish.seconds);
}
int best = 0;
for (int i = 1; i < n; i++) {
if (faster(&runners[i], &runners[best])) {
best = i;
}
}
Time t = from_seconds(used(&runners[best]));
printf("%s %d %d %d\n", runners[best].name, t.hours, t.minutes, t.seconds);
return 0;
}ข้อ 5 คลังสินค้า
คลังสินค้าของร้านเครื่องเขียนมีสินค้า M ชนิด แต่ละชนิดมีรหัสไม่ซ้ำกัน จำนวนที่มีอยู่ในคลัง และราคาต่อชิ้น วันนี้มีคำสั่ง Q คำสั่งเข้ามาตามลำดับ คำสั่งมีสองแบบ
IN รหัส Kรับสินค้ารหัสนั้นเข้าคลัง K ชิ้นOUT รหัส Kเบิกสินค้ารหัสนั้นออก K ชิ้น ถ้าในคลังมีน้อยกว่า K ชิ้น คำสั่งนี้ถูกปฏิเสธ ไม่มีการเบิกออกเลยแม้แต่ชิ้นเดียว
หลังทำครบทุกคำสั่ง ให้รายงานจำนวนคงเหลือของสินค้าทุกชนิด มูลค่ารวมของสินค้าทั้งคลัง คือผลรวมของจำนวนคงเหลือคูณราคาต่อชิ้นของทุกชนิด และจำนวนคำสั่งที่ถูกปฏิเสธ
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม M และ Q โดยที่ 1 ≤ M ≤ 100 และ 1 ≤ Q ≤ 1000
อีก M บรรทัด แต่ละบรรทัดมีรหัสสินค้า จำนวนเริ่มต้น และราคาต่อชิ้น คั่นด้วยช่องว่าง รหัสเป็นตัวอักษรภาษาอังกฤษตัวพิมพ์ใหญ่หรือตัวเลข ยาว 1 ถึง 10 ตัว จำนวนเริ่มต้นอยู่ระหว่าง 0 ถึง 106 และราคาอยู่ระหว่าง 1 ถึง 106
อีก Q บรรทัด แต่ละบรรทัดเป็นคำสั่งหนึ่งคำสั่งตามรูปแบบข้างบน รหัสในคำสั่งมีอยู่ในคลังแน่นอน และ 1 ≤ K ≤ 106
ข้อมูลออก
M บรรทัดแรก พิมพ์รหัสและจำนวนคงเหลือของสินค้าแต่ละชนิด คั่นด้วยช่องว่าง เรียงตามลำดับในข้อมูลเข้า บรรทัดถัดไปพิมพ์มูลค่ารวมของสินค้าทั้งคลัง และบรรทัดสุดท้ายพิมพ์จำนวนคำสั่งที่ถูกปฏิเสธ
3 5
PEN01 50 12
ERASER 20 5
RULER30 0 25
OUT PEN01 30
OUT RULER30 1
IN RULER30 10
OUT PEN01 25
OUT ERASER 20PEN01 20
ERASER 0
RULER30 10
490
21 2
A 5 100
IN A 3
OUT A 9A 8
800
1ดูคำใบ้
เก็บสินค้าเป็นอาเรย์ของ struct ที่มีรหัส จำนวน และราคา แล้วเขียนฟังก์ชันหาว่ารหัสนี้อยู่ช่องไหนด้วย strcmp แบบหน้า 11.2 อ่านชนิดคำสั่งด้วย %s แล้วเทียบกับ "IN" ระวังสองเรื่อง เบิกได้เมื่อของมีมากกว่าหรือเท่ากับที่ขอ และมูลค่าของสินค้าหนึ่งชนิดใหญ่ได้ถึงประมาณ 1015 ต้องแปลงเป็น long long ก่อนคูณ
ดูเฉลย
#include <stdio.h>
#include <string.h>
typedef struct {
char code[11];
int quantity;
int price;
} Item;
Item items[100];
int find_item(const char code[], int m)
{
for (int i = 0; i < m; i++) {
if (strcmp(items[i].code, code) == 0) {
return i;
}
}
return -1;
}
int main()
{
int m, q;
scanf("%d %d", &m, &q);
for (int i = 0; i < m; i++) {
scanf("%s %d %d", items[i].code, &items[i].quantity, &items[i].price);
}
int rejected = 0;
for (int k = 0; k < q; k++) {
char type[4], code[11];
int amount;
scanf("%s %s %d", type, code, &amount);
Item *item = &items[find_item(code, m)];
if (strcmp(type, "IN") == 0) {
item->quantity += amount;
} else if (item->quantity >= amount) {
item->quantity -= amount;
} else {
rejected++;
}
}
long long total = 0;
for (int i = 0; i < m; i++) {
printf("%s %d\n", items[i].code, items[i].quantity);
total += (long long)items[i].quantity * items[i].price;
}
printf("%lld\n", total);
printf("%d\n", rejected);
return 0;
}ข้อ 6 พื้นที่ที่กล้องทุกตัวเห็น
ลานจอดรถติดกล้องวงจรปิด N ตัว กล้องแต่ละตัวมองเห็นพื้นที่เป็นสี่เหลี่ยมผืนผ้าที่ด้านขนานกับแกน x และแกน y ช่างที่ติดตั้งจดพื้นที่ของกล้องแต่ละตัวไว้เป็นพิกัดของมุมสองมุมที่อยู่ตรงข้ามกัน แต่ไม่ได้จดว่ามุมไหนเป็นมุมไหน อาจเป็นมุมซ้ายล่างกับมุมขวาบน หรือมุมซ้ายบนกับมุมขวาล่าง และจดมุมไหนก่อนก็ได้
ฝ่ายรักษาความปลอดภัยอยากรู้ว่า พื้นที่ส่วนที่ กล้องทุกตัว มองเห็นพร้อมกันมีขนาดกี่ตารางหน่วย ถ้าไม่มีพื้นที่แบบนั้น หรือส่วนที่ทุกตัวเห็นเป็นแค่เส้นหรือจุด ให้ตอบ 0
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N โดยที่ 1 ≤ N ≤ 100000
อีก N บรรทัด แต่ละบรรทัดมีจำนวนเต็ม x1 y1 x2 y2 คั่นด้วยช่องว่าง หมายถึงกล้องตัวหนึ่งเห็นสี่เหลี่ยมที่มีมุมตรงข้ามกันอยู่ที่ (x1, y1) และ (x2, y2) รับประกันว่า x1 ≠ x2 และ y1 ≠ y2 พิกัดทุกตัวอยู่ระหว่าง -109 ถึง 109
ข้อมูลออก
พื้นที่ส่วนที่กล้องทุกตัวมองเห็น
2
0 0 6 4
3 1 8 593
10 10 2 3
0 8 7 0
5 12 1 412ดูคำใบ้
เขียนฟังก์ชันรับมุมสองมุม แล้วคืน Rect ที่มี low เป็นมุมซ้ายล่างและ high เป็นมุมขวาบนจริงๆ ตามหน้า 11.4 จากนั้นใช้วิธีหาส่วนที่ทับกันในหน้า 11.3 กับกล้องทีละตัว ส่วนที่ทุกตัวเห็นมีขอบซ้ายเป็นค่ามากของขอบซ้ายทุกตัว และขอบขวาเป็นค่าน้อยของขอบขวาทุกตัว อย่าลืมกรณีที่ไม่ทับกันทั้งแนวนอนและแนวตั้งพร้อมกัน และพื้นที่ใหญ่ถึง 4 × 1018
ดูเฉลย
#include <stdio.h>
typedef struct {
long long x;
long long y;
} Point;
typedef struct {
Point low;
Point high;
} Rect;
long long min_ll(long long a, long long b)
{
return a < b ? a : b;
}
long long max_ll(long long a, long long b)
{
return a > b ? a : b;
}
Rect make_rect(Point a, Point b)
{
Rect r;
r.low.x = min_ll(a.x, b.x);
r.low.y = min_ll(a.y, b.y);
r.high.x = max_ll(a.x, b.x);
r.high.y = max_ll(a.y, b.y);
return r;
}
Rect read_rect()
{
Point a, b;
scanf("%lld %lld %lld %lld", &a.x, &a.y, &b.x, &b.y);
return make_rect(a, b);
}
int main()
{
int n;
scanf("%d", &n);
Rect common = read_rect();
for (int i = 1; i < n; i++) {
Rect r = read_rect();
common.low.x = max_ll(common.low.x, r.low.x);
common.low.y = max_ll(common.low.y, r.low.y);
common.high.x = min_ll(common.high.x, r.high.x);
common.high.y = min_ll(common.high.y, r.high.y);
}
long long width = common.high.x - common.low.x;
long long height = common.high.y - common.low.y;
if (width > 0 && height > 0) {
printf("%lld\n", width * height);
} else {
printf("0\n");
}
return 0;
}ข้อ 7 ตารางคะแนนลีก
ลีกฟุตบอลของโรงเรียนมี T ทีม ตลอดฤดูกาลแข่งไป M นัด ทีมสองทีมอาจเจอกันได้หลายครั้ง หรือไม่เจอกันเลยก็ได้ แต่ละนัดให้แต้มแบบนี้ ชนะได้ 3 แต้ม เสมอได้ 1 แต้ม แพ้ได้ 0 แต้ม
อันดับในตารางตัดสินตามเกณฑ์ต่อไปนี้ทีละข้อ ถ้าข้อก่อนหน้าเท่ากันจึงดูข้อถัดไป
- แต้มรวมมากกว่าอยู่สูงกว่า
- ผลต่างประตู คือประตูที่ยิงได้ทั้งหมดลบประตูที่เสียทั้งหมด มากกว่าอยู่สูงกว่า
- ประตูที่ยิงได้ทั้งหมดมากกว่าอยู่สูงกว่า
- ชื่อทีมที่มาก่อนตามลำดับพจนานุกรมอยู่สูงกว่า โดยเทียบแบบเดียวกับ
strcmp
ให้พิมพ์สามทีมแรกของตาราง
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม T และ M โดยที่ 3 ≤ T ≤ 20 และ 0 ≤ M ≤ 500
บรรทัดที่สองมีชื่อทีม T ชื่อ คั่นด้วยช่องว่าง ชื่อเป็นตัวอักษรภาษาอังกฤษยาว 1 ถึง 15 ตัว ไม่ซ้ำกัน
อีก M บรรทัด แต่ละบรรทัดเป็นผลการแข่งขันหนึ่งนัด มีชื่อทีม A ชื่อทีม B จำนวนประตูที่ A ยิงได้ และจำนวนประตูที่ B ยิงได้ คั่นด้วยช่องว่าง A กับ B เป็นคนละทีมกันเสมอ และจำนวนประตูอยู่ระหว่าง 0 ถึง 20
ข้อมูลออก
สามบรรทัด เป็นทีมอันดับที่ 1 ถึง 3 ตามลำดับ แต่ละบรรทัดมีชื่อทีม แต้มรวม ผลต่างประตู และประตูที่ยิงได้ทั้งหมด คั่นด้วยช่องว่าง
4 6
Lions Tigers Eagles Sharks
Lions Tigers 2 1
Eagles Sharks 0 0
Lions Eagles 1 3
Tigers Sharks 4 0
Lions Sharks 2 2
Tigers Eagles 1 1Eagles 5 2 4
Tigers 4 3 6
Lions 4 -1 54 3
Alpha Beta Gamma Delta
Alpha Gamma 10 9
Beta Delta 3 0
Gamma Delta 0 0Beta 3 3 3
Alpha 3 1 10
Gamma 1 -1 9ดูคำใบ้
เก็บทีมเป็น struct ที่มีชื่อ แต้ม ประตูได้ และประตูเสีย ทุกนัดหาว่าสองทีมอยู่ช่องไหนด้วย strcmp แล้วบวกค่าให้ทั้งสองทีม จากนั้นเขียนฟังก์ชัน better แบบหน้า 11.4 ที่ไล่ดูทีละเกณฑ์ ต้องการแค่สามอันดับแรก จึงไม่ต้องเรียงทั้งตาราง หาทีมที่ดีที่สุดในบรรดาทีมที่ยังไม่ถูกเลือก ทำสามรอบ และใช้อาเรย์ used จำว่าทีมไหนถูกเลือกไปแล้ว
ดูเฉลย
#include <stdio.h>
#include <string.h>
typedef struct {
char name[16];
int points;
int scored;
int conceded;
} Team;
Team teams[20];
int used[20];
int find_team(const char name[], int t)
{
for (int i = 0; i < t; i++) {
if (strcmp(teams[i].name, name) == 0) {
return i;
}
}
return -1;
}
void record(Team *team, int scored, int conceded)
{
team->scored += scored;
team->conceded += conceded;
if (scored > conceded) {
team->points += 3;
} else if (scored == conceded) {
team->points += 1;
}
}
int better(const Team *a, const Team *b)
{
if (a->points != b->points) {
return a->points > b->points;
}
int diff_a = a->scored - a->conceded;
int diff_b = b->scored - b->conceded;
if (diff_a != diff_b) {
return diff_a > diff_b;
}
if (a->scored != b->scored) {
return a->scored > b->scored;
}
return strcmp(a->name, b->name) < 0;
}
int main()
{
int t, m;
scanf("%d %d", &t, &m);
for (int i = 0; i < t; i++) {
scanf("%s", teams[i].name);
}
for (int k = 0; k < m; k++) {
char home[16], away[16];
int home_goals, away_goals;
scanf("%s %s %d %d", home, away, &home_goals, &away_goals);
record(&teams[find_team(home, t)], home_goals, away_goals);
record(&teams[find_team(away, t)], away_goals, home_goals);
}
for (int rank = 0; rank < 3; rank++) {
int best = -1;
for (int i = 0; i < t; i++) {
if (!used[i] && (best == -1 || better(&teams[i], &teams[best]))) {
best = i;
}
}
used[best] = 1;
printf("%s %d %d %d\n", teams[best].name, teams[best].points,
teams[best].scored - teams[best].conceded, teams[best].scored);
}
return 0;
}ข้อ 8 หุ่นยนต์ส่งของ
โกดังขนาดใหญ่ใช้หุ่นยนต์ N ตัวขนของบนพื้นที่แบ่งเป็นช่องตาราง ช่องแต่ละช่องมีพิกัดเป็นจำนวนเต็ม (x, y) หุ่นยนต์แต่ละตัวมีตำแหน่งเริ่มต้น และหันหน้าไปทางทิศใดทิศหนึ่งในสี่ทิศ คือ N เหนือ E ตะวันออก S ใต้ และ W ตะวันตก เดินไปทางเหนือหนึ่งช่อง y เพิ่มหนึ่ง เดินไปทางตะวันออกหนึ่งช่อง x เพิ่มหนึ่ง ทิศใต้และตะวันตกลดลงในทำนองเดียวกัน
ศูนย์ควบคุมส่งคำสั่ง Q คำสั่งตามลำดับ แต่ละคำสั่งสั่งหุ่นยนต์ทีละตัว มีสามแบบ
i F Kหุ่นยนต์ตัวที่ i เดินตรงไปข้างหน้าตามทิศที่หันอยู่ K ช่องi Lหุ่นยนต์ตัวที่ i หมุนตัวไปทางซ้าย 90 องศา อยู่ที่ช่องเดิมi Rหุ่นยนต์ตัวที่ i หมุนตัวไปทางขวา 90 องศา อยู่ที่ช่องเดิม
หุ่นยนต์เดินผ่านกันและอยู่ช่องเดียวกันได้ หลังทำครบทุกคำสั่ง ให้รายงานตำแหน่งและทิศของหุ่นยนต์ทุกตัว และนับว่ามีหุ่นยนต์กี่คู่ที่หยุดอยู่ในช่องเดียวกัน ถ้ามีสามตัวอยู่ช่องเดียวกัน นับเป็น 3 คู่
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N และ Q โดยที่ 1 ≤ N ≤ 1000 และ 0 ≤ Q ≤ 100000
อีก N บรรทัด บรรทัดที่ i มีจำนวนเต็ม x y และตัวอักษร d คั่นด้วยช่องว่าง เป็นตำแหน่งและทิศเริ่มต้นของหุ่นยนต์ตัวที่ i โดยที่ -109 ≤ x, y ≤ 109 และ d เป็นหนึ่งใน N E S W
อีก Q บรรทัด แต่ละบรรทัดเป็นคำสั่งหนึ่งคำสั่งตามรูปแบบข้างบน โดยที่ 1 ≤ i ≤ N และ 1 ≤ K ≤ 109
ข้อมูลออก
N บรรทัดแรก บรรทัดที่ i มีพิกัด x y และทิศสุดท้ายของหุ่นยนต์ตัวที่ i คั่นด้วยช่องว่าง บรรทัดสุดท้ายพิมพ์จำนวนคู่ของหุ่นยนต์ที่อยู่ในช่องเดียวกัน
3 7
0 0 N
3 2 W
-1 5 E
1 F 2
1 R
1 F 3
2 L
3 F 4
3 R
3 F 33 2 E
3 2 S
3 2 S
34 8
0 0 E
5 5 S
2 -3 N
9 9 W
1 F 5
2 F 5
3 F 3
3 R
3 F 3
4 L
4 L
4 L5 0 E
5 0 S
5 0 E
9 9 N
3ดูคำใบ้
เก็บทิศเป็นเลข 0 ถึง 3 แทน N E S W ตามลำดับตามเข็มนาฬิกา เลี้ยวขวาคือบวกหนึ่งแล้ว % 4 เลี้ยวซ้ายคือบวกสามแล้ว % 4 และเตรียมอาเรย์ dx กับ dy สี่ช่องไว้บอกว่าแต่ละทิศเดินแล้วพิกัดเปลี่ยนเท่าไร เขียนฟังก์ชันรับ Robot * แล้วแก้ผ่าน -> ตามหน้า 11.4 พิกัดไปได้ไกลถึงประมาณ 1014 ต้องใช้ long long ส่วนการนับคู่ที่อยู่ช่องเดียวกัน เทียบทุกคู่ได้เลย เพราะ N ไม่เกิน 1000
ดูเฉลย
#include <stdio.h>
typedef struct {
long long x;
long long y;
} Point;
typedef struct {
Point pos;
int dir;
} Robot;
const char DIRECTIONS[] = "NESW";
const int DX[4] = {0, 1, 0, -1};
const int DY[4] = {1, 0, -1, 0};
Robot robots[1000];
int direction_index(char d)
{
for (int i = 0; i < 4; i++) {
if (DIRECTIONS[i] == d) {
return i;
}
}
return -1;
}
void turn_left(Robot *r)
{
r->dir = (r->dir + 3) % 4;
}
void turn_right(Robot *r)
{
r->dir = (r->dir + 1) % 4;
}
void forward(Robot *r, long long steps)
{
r->pos.x += DX[r->dir] * steps;
r->pos.y += DY[r->dir] * steps;
}
int main()
{
int n, q;
scanf("%d %d", &n, &q);
for (int i = 0; i < n; i++) {
char d;
scanf("%lld %lld %c", &robots[i].pos.x, &robots[i].pos.y, &d);
robots[i].dir = direction_index(d);
}
for (int k = 0; k < q; k++) {
int id;
char command;
scanf("%d %c", &id, &command);
Robot *r = &robots[id - 1];
if (command == 'F') {
long long steps;
scanf("%lld", &steps);
forward(r, steps);
} else if (command == 'L') {
turn_left(r);
} else {
turn_right(r);
}
}
int pairs = 0;
for (int i = 0; i < n; i++) {
printf("%lld %lld %c\n", robots[i].pos.x, robots[i].pos.y, DIRECTIONS[robots[i].dir]);
for (int j = i + 1; j < n; j++) {
if (robots[i].pos.x == robots[j].pos.x && robots[i].pos.y == robots[j].pos.y) {
pairs++;
}
}
}
printf("%d\n", pairs);
return 0;
}