13.6 แบบฝึกหัด
เขียนแต่ละข้อเป็นไฟล์ใหม่ใน Code::Blocks รันแล้วเทียบกับผลลัพธ์ที่ต้องได้ให้ตรงทุกตัวอักษร รวมถึงช่องว่างและการขึ้นบรรทัด ติดจริงๆ ค่อยเปิดคำใบ้ และเปิดเฉลยหลังทำเสร็จแล้วเท่านั้น
ข้อ 1 เข้าแถวตามส่วนสูง
ครูพละให้นักเรียน N คนเข้าแถวหน้าเสาธงโดยเรียงจากคนที่เตี้ยที่สุดไปคนที่สูงที่สุด ครูจดส่วนสูงของทุกคนเป็นเซนติเมตรตามลำดับที่เดินมาถึง ให้พิมพ์ส่วนสูงเรียงตามลำดับในแถว
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N (1 ≤ N ≤ 1000)
บรรทัดที่สองมีส่วนสูงของนักเรียน N จำนวน คั่นด้วยช่องว่าง แต่ละจำนวนเป็นจำนวนเต็มตั้งแต่ 100 ถึง 200
ข้อมูลออก
บรรทัดเดียว ส่วนสูงทั้ง N จำนวนเรียงจากน้อยไปมาก คั่นด้วยช่องว่างหนึ่งช่อง
6
152 148 160 155 149 171148 149 152 155 160 1715
160 155 160 148 155148 155 155 160 160ดูคำใบ้
N ไม่เกิน 1000 ใช้วิธีเรียงที่เขียนเองในหน้า 13.2 หรือ 13.3 ได้สบาย อ่านส่วนสูงทั้งหมดเข้าอาเรย์ก่อน เรียง แล้วค่อยพิมพ์ ส่วนสูงที่เท่ากันต้องพิมพ์ครบทุกคน ถ้าผลมีบางค่าซ้ำแปลกๆ หรือหายไป ให้ตรวจการสลับว่ามีตัวแปรพักแล้วหรือยัง
ดูเฉลย
#include <stdio.h>
int height[1000];
void insertion_sort(int a[], int n)
{
for (int i = 1; i < n; i++) {
int key = a[i];
int j = i - 1;
while (j >= 0 && a[j] > key) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = key;
}
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &height[i]);
}
insertion_sort(height, n);
for (int i = 0; i < n; i++) {
if (i > 0) {
printf(" ");
}
printf("%d", height[i]);
}
printf("\n");
return 0;
}ข้อ 2 เวลากลางของนักวิ่ง
งานวิ่งการกุศลของโรงเรียนมีนักวิ่ง N คน เครื่องจับเวลาบันทึกเวลาที่แต่ละคนใช้เป็นวินาที ตามลำดับเลขบิบ ไม่ได้เรียงตามเวลา ผู้จัดอยากประกาศว่านักวิ่ง "ทั่วไป" ใช้เวลาเท่าไร จึงต้องการค่ากลาง คือเวลาของคนที่อยู่ตรงกลางพอดีเมื่อเรียงเวลาของทุกคนจากน้อยไปมาก N เป็นเลขคี่เสมอ
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็มคี่ N (1 ≤ N ≤ 999)
บรรทัดที่สองมีเวลาของนักวิ่ง N คน คั่นด้วยช่องว่าง แต่ละค่าเป็นจำนวนเต็มตั้งแต่ 1 ถึง 100000
ข้อมูลออก
ค่ากลางของเวลาทั้ง N ค่า
5
1820 1795 2410 1650 360018207
2100 1980 2100 2650 1700 2100 19902100ดูคำใบ้
ข้อมูลยังไม่เรียง ต้องเรียงก่อน แล้วค่ากลางคือช่อง N / 2 ตามหน้า 13.1 ถ้าตอบช่อง N / 2 ของข้อมูลที่ยังไม่เรียง จะผ่านเฉพาะชุดที่บังเอิญเรียงมาแล้ว
ดูเฉลย
#include <stdio.h>
int seconds[1000];
void swap(int *x, int *y)
{
int temp = *x;
*x = *y;
*y = temp;
}
void selection_sort(int a[], int n)
{
for (int i = 0; i < n - 1; i++) {
int min_index = i;
for (int j = i + 1; j < n; j++) {
if (a[j] < a[min_index]) {
min_index = j;
}
}
swap(&a[i], &a[min_index]);
}
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &seconds[i]);
}
selection_sort(seconds, n);
printf("%d\n", seconds[n / 2]);
return 0;
}ข้อ 3 ห้องเก็บของหาย
ห้องเก็บของหายของโรงเรียนวางกล่องเรียงเป็นแถวยาว N กล่อง กล่องที่ 1 อยู่ซ้ายสุด แต่ละกล่องติดป้ายเลขรหัสของสิ่งของในกล่อง ของหลายชิ้นอาจมีรหัสเดียวกันได้ เช่น ขวดน้ำรุ่นเดียวกัน นักเรียนคนหนึ่งมาถามหาของรหัส X ให้บอกว่ามีกล่องที่ติดรหัส X กี่กล่อง และอยู่กล่องที่เท่าไรบ้าง
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N และ X คั่นด้วยช่องว่าง (1 ≤ N ≤ 1000 และ 1 ≤ X ≤ 109)
บรรทัดที่สองมีรหัสบนกล่องที่ 1 ถึงกล่องที่ N คั่นด้วยช่องว่าง แต่ละรหัสเป็นจำนวนเต็มตั้งแต่ 1 ถึง 109
ข้อมูลออก
บรรทัดแรกพิมพ์จำนวนกล่องที่ติดรหัส X
ถ้าจำนวนนั้นมากกว่า 0 บรรทัดที่สองพิมพ์ลำดับของกล่องเหล่านั้นจากซ้ายไปขวา คั่นด้วยช่องว่างหนึ่งช่อง ถ้าไม่มีกล่องใดเลย ให้พิมพ์แค่บรรทัดแรก
6 870
1024 5531 870 4410 870 99022
3 54 77
12 34 56 780ดูคำใบ้
ค้นหาแบบไล่ในหน้า 13.5 แต่ต้องไล่ให้ครบทุกกล่อง ห้ามหยุดที่กล่องแรกที่เจอ จำนวนต้องพิมพ์ก่อนลำดับกล่อง จึงต้องรู้จำนวนก่อน จะไล่สองรอบ หรือเก็บลำดับที่เจอไว้ในอาเรย์ก็ได้ ลำดับกล่องเริ่มนับจาก 1 ไม่ใช่ 0 และอย่าพิมพ์ว่าไม่เจอไว้ในลูป
ดูเฉลย
#include <stdio.h>
int code[1000];
int found[1000];
int main()
{
int n, target;
scanf("%d %d", &n, &target);
for (int i = 0; i < n; i++) {
scanf("%d", &code[i]);
}
int count = 0;
for (int i = 0; i < n; i++) {
if (code[i] == target) {
found[count] = i + 1;
count++;
}
}
printf("%d\n", count);
if (count > 0) {
for (int i = 0; i < count; i++) {
if (i > 0) {
printf(" ");
}
printf("%d", found[i]);
}
printf("\n");
}
return 0;
}ข้อ 4 ล่าคำในบทความ
น้องกำลังทำรายงาน และอยากรู้ว่าคำที่สนใจปรากฏในบทความบ่อยแค่ไหน บทความพิมพ์มาทั้งตัวพิมพ์ใหญ่และตัวพิมพ์เล็กปนกัน น้องจึงอยากให้นับโดยไม่สนตัวพิมพ์ เช่น the The และ THE ถือว่าตรงกันทั้งหมด
ให้นับว่ามีกี่ตำแหน่งในบทความที่ถ้าเริ่มอ่านจากตำแหน่งนั้นแล้วจะได้คำที่ค้นหา คำที่ค้นหาอาจอยู่ในคำอื่น เช่น the ใน other ก็นับ และตำแหน่งที่พบอาจซ้อนกันได้ เช่น ana ใน banana นับเป็น 2 ครั้ง
ข้อมูลเข้า
บรรทัดแรกคือบทความ ยาว 1 ถึง 1000 ตัวอักษร ประกอบด้วยตัวอักษรภาษาอังกฤษพิมพ์ใหญ่หรือพิมพ์เล็ก และช่องว่าง
บรรทัดที่สองคือคำที่ค้นหา ยาว 1 ถึง 100 ตัวอักษร ประกอบด้วยตัวอักษรภาษาอังกฤษพิมพ์ใหญ่หรือพิมพ์เล็กเท่านั้น
ข้อมูลออก
บรรทัดเดียว มีจำนวนครั้งที่พบ ตามด้วยช่องว่าง แล้วตามด้วยตำแหน่งแรกที่พบ โดยตัวอักษรตัวแรกของบทความคือตำแหน่งที่ 1 ถ้าไม่พบเลยให้พิมพ์ 0 -1
The cat sat on THE mat with the other cat
the4 1BaNaNa bandana
ANA3 2ดูคำใบ้
ใช้การหาคำแบบลองทุกตำแหน่งเริ่มในหน้า 13.5 แต่ตอนเทียบทีละตัวให้แปลงทั้งสองฝั่งเป็นตัวพิมพ์เล็กก่อน ด้วย tolower จาก ctype.h ในหน้า 6.1 อ่านทั้งสองบรรทัดด้วย fgets และตัด '\n' ทิ้งทั้งคู่ คำที่ค้นหาอาจยาวกว่าบทความ ซึ่งต้องตอบ 0 -1 ตำแหน่งที่พิมพ์เริ่มนับจาก 1
ดูเฉลย
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char text[1005], word[105];
void strip_newline(char s[])
{
for (int i = 0; s[i] != '\0'; i++) {
if (s[i] == '\n' || s[i] == '\r') {
s[i] = '\0';
}
}
}
int main()
{
fgets(text, sizeof text, stdin);
fgets(word, sizeof word, stdin);
strip_newline(text);
strip_newline(word);
int n = strlen(text);
int m = strlen(word);
int count = 0;
int first = -1;
for (int i = 0; i + m <= n; i++) {
int j = 0;
while (j < m && tolower(text[i + j]) == tolower(word[j])) {
j++;
}
if (j == m) {
if (count == 0) {
first = i + 1;
}
count++;
}
}
printf("%d %d\n", count, first);
return 0;
}ข้อ 5 ทะเบียนรถที่ด่าน
กล้องที่ด่านเก็บค่าผ่านทางอ่านทะเบียนรถทุกคันที่ผ่านในวันหนึ่ง แล้วแปลงเป็นรหัสตัวเลข รถคันเดียวกันได้รหัสเดิมทุกครั้ง และรถบางคันผ่านด่านหลายรอบ วันนี้กล้องอ่านได้ N ครั้ง ให้หาว่ามีรถที่ต่างกันกี่คัน และรถคันที่ผ่านบ่อยที่สุดผ่านกี่ครั้ง
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N (1 ≤ N ≤ 100000)
บรรทัดที่สองมีรหัสที่อ่านได้ N รหัสตามลำดับเวลา คั่นด้วยช่องว่าง แต่ละรหัสเป็นจำนวนเต็มตั้งแต่ 1 ถึง 109
ข้อมูลออก
บรรทัดเดียว มีจำนวนรถที่ต่างกัน ตามด้วยช่องว่าง แล้วตามด้วยจำนวนครั้งที่รถคันที่ผ่านบ่อยที่สุดผ่านด่าน
7
5521 120 5521 98000 120 5521 74 33
1000000000 1 9999999993 1ดูคำใบ้
รหัสใหญ่ถึง 109 ใช้อาเรย์นับแบบหน้า 5.3 ไม่ได้ ให้เรียงก่อน รหัสเดียวกันจะอยู่ติดกันเป็นกลุ่ม แล้วนับกลุ่มกับความยาวของกลุ่มแบบตัวอย่างราคาขนมในหน้า 13.1 N ถึงแสน bubble sort เทียบราว 5 × 109 ครั้ง ไม่ทัน ต้องใช้ qsort จากหน้า 13.4 อย่าลืมปิดกลุ่มสุดท้ายหลังจบลูป
ดูเฉลย
#include <stdio.h>
#include <stdlib.h>
int plate[100000];
int compare_int(const void *p, const void *q)
{
int x = *(const int *)p;
int y = *(const int *)q;
if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &plate[i]);
}
qsort(plate, n, sizeof(int), compare_int);
int distinct = 0;
int most = 0;
int start = 0;
for (int i = 1; i <= n; i++) {
if (i == n || plate[i] != plate[i - 1]) {
distinct++;
if (i - start > most) {
most = i - start;
}
start = i;
}
}
printf("%d %d\n", distinct, most);
return 0;
}ข้อ 6 คะแนนของอันดับที่ k
การสอบคัดเลือกเข้าโรงเรียนแห่งหนึ่งมีผู้สมัคร N คน คะแนนเต็ม 100 ผู้สมัครแต่ละคนได้คะแนนเป็นจำนวนเต็ม เมื่อเรียงคะแนนของทุกคนจากมากไปน้อย คนแรกในรายการคืออันดับที่ 1 คนถัดไปคืออันดับที่ 2 ไปเรื่อยๆ ถ้ามีคนได้คะแนนเท่ากัน ใครอยู่ก่อนก็ได้ เพราะคะแนนที่ตำแหน่งนั้นเท่าเดิม
โรงเรียนมีคำถาม Q ข้อ แต่ละข้อถามว่าผู้สมัครอันดับที่ k ได้คะแนนเท่าไร เช่น ถ้ารับ 300 คน ก็อยากรู้คะแนนของอันดับที่ 300 ซึ่งเป็นคะแนนต่ำสุดที่ยังได้เข้าเรียน
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N และ Q คั่นด้วยช่องว่าง (1 ≤ N ≤ 200000 และ 1 ≤ Q ≤ 1000)
บรรทัดที่สองมีคะแนนของผู้สมัคร N คน คั่นด้วยช่องว่าง แต่ละคะแนนเป็นจำนวนเต็มตั้งแต่ 0 ถึง 100
อีก Q บรรทัด บรรทัดละหนึ่งจำนวนเต็ม k (1 ≤ k ≤ N)
ข้อมูลออก
Q บรรทัด บรรทัดที่ i คือคะแนนของผู้สมัครอันดับที่ k ของคำถามข้อที่ i
6 4
72 85 64 85 90 58
1
2
3
690
85
85
585 4
50 50 50 40 40
3
4
5
150
40
40
50ดูคำใบ้
คะแนนมีแค่ 101 ค่า ใช้ counting sort ในหน้า 13.5 นับว่าแต่ละคะแนนมีกี่คน แล้วตอบคำถามโดยไล่คะแนนจาก 100 ลงมา สะสมจำนวนคนไปเรื่อยๆ คะแนนแรกที่จำนวนสะสมถึง k คือคำตอบ หรือจะสร้างรายการที่เรียงจากมากไปน้อยด้วย counting sort ก่อนแล้วตอบช่อง k - 1 ก็ได้ N ถึงสองแสน bubble sort ไม่ทัน
ดูเฉลย
#include <stdio.h>
int count[101];
int main()
{
int n, q;
scanf("%d %d", &n, &q);
for (int i = 0; i < n; i++) {
int score;
scanf("%d", &score);
count[score]++;
}
for (int i = 0; i < q; i++) {
int k;
scanf("%d", &k);
int passed = 0;
int score = 100;
while (passed + count[score] < k) {
passed += count[score];
score--;
}
printf("%d\n", score);
}
return 0;
}ข้อ 7 ตารางอันดับ
การแข่งขันเขียนโปรแกรมของโรงเรียนมีผู้เข้าแข่ง N คน เมื่อหมดเวลา แต่ละคนมีจำนวนข้อที่ทำผ่าน และเวลาปรับ (penalty) เป็นนาที กรรมการจัดตารางอันดับตามกติกานี้
- ทำผ่านมากข้อกว่า อยู่ก่อน
- ถ้าทำผ่านเท่ากัน เวลาปรับน้อยกว่า อยู่ก่อน
- ถ้าทั้งสองอย่างเท่ากัน ถือว่าได้อันดับเดียวกัน แต่ในตารางให้เรียงตามชื่อตามลำดับพจนานุกรม
อันดับของแต่ละคนคือ 1 บวกจำนวนคนที่ทำได้ดีกว่าคนนั้นจริงๆ เช่น ถ้ามีสองคนเสมอกันที่อันดับ 2 คนถัดไปจะได้อันดับ 4 ไม่ใช่ 3
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N (1 ≤ N ≤ 50000)
อีก N บรรทัด บรรทัดละหนึ่งคน มีชื่อ จำนวนข้อที่ทำผ่าน และเวลาปรับ คั่นด้วยช่องว่าง ชื่อเป็นตัวพิมพ์เล็กภาษาอังกฤษยาว 1 ถึง 10 ตัว และไม่มีชื่อซ้ำกัน จำนวนข้อเป็นจำนวนเต็มตั้งแต่ 0 ถึง 10 เวลาปรับเป็นจำนวนเต็มตั้งแต่ 0 ถึง 100000
ข้อมูลออก
N บรรทัดตามลำดับในตาราง บรรทัดละหนึ่งคน มีอันดับ ตามด้วยช่องว่าง แล้วตามด้วยชื่อ
6
somchai 3 120
malee 4 300
anan 3 95
kanya 3 120
preeda 1 10
boonmee 3 1201 malee
2 anan
3 boonmee
3 kanya
3 somchai
6 preeda2
zed 0 0
amy 0 01 amy
1 zedดูคำใบ้
เก็บแต่ละคนเป็น struct แล้วเรียงด้วย qsort ตามสามเงื่อนไขแบบหน้า 13.4 เงื่อนไขแรกที่ต่างกันเป็นตัวตัดสิน ห้ามลบกันในฟังก์ชันเปรียบเทียบ หลังเรียงแล้วไล่คำนวณอันดับ คนแรกได้อันดับ 1 คนต่อไปถ้าจำนวนข้อและเวลาปรับเท่ากับคนก่อนหน้าให้ได้อันดับเดียวกับคนก่อนหน้า ไม่อย่างนั้นได้อันดับเท่ากับตำแหน่งของตัวเองในตาราง (เริ่มนับจาก 1) N ถึงห้าหมื่น bubble sort ไม่ทัน
ดูเฉลย
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct contestant {
char name[11];
int solved;
int penalty;
};
struct contestant list[50000];
int compare_rank(const void *p, const void *q)
{
const struct contestant *a = p;
const struct contestant *b = q;
if (a->solved != b->solved) {
return a->solved > b->solved ? -1 : 1;
}
if (a->penalty != b->penalty) {
return a->penalty < b->penalty ? -1 : 1;
}
return strcmp(a->name, b->name);
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%s %d %d", list[i].name, &list[i].solved, &list[i].penalty);
}
qsort(list, n, sizeof(list[0]), compare_rank);
int rank = 0;
for (int i = 0; i < n; i++) {
if (i == 0 || list[i].solved != list[i - 1].solved || list[i].penalty != list[i - 1].penalty) {
rank = i + 1;
}
printf("%d %s\n", rank, list[i].name);
}
return 0;
}ข้อ 8 สถานีที่ตรวจพบใกล้กันที่สุด
เครือข่ายเฝ้าระวังแผ่นดินไหวมีสถานีตรวจวัด N สถานี แต่ละสถานีบันทึกเวลาที่ตรวจพบคลื่นเป็นมิลลิวินาที เทียบกับเวลาอ้างอิงของเครือข่าย ค่าติดลบคือก่อนเวลาอ้างอิง นักวิจัยอยากรู้ว่าสองสถานีที่ตรวจพบใกล้กันที่สุดห่างกันกี่มิลลิวินาที และมีสถานีกี่คู่ที่ห่างกันเท่านั้นพอดี
ระยะห่างของสถานี i กับสถานี j คือค่าสัมบูรณ์ของผลต่างของเวลา คู่ (i, j) กับ (j, i) นับเป็นคู่เดียวกัน และสองสถานีอาจตรวจพบในเวลาเดียวกันได้
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N (2 ≤ N ≤ 100000)
บรรทัดที่สองมีเวลาของสถานีที่ 1 ถึงสถานีที่ N คั่นด้วยช่องว่าง แต่ละค่าเป็นจำนวนเต็มตั้งแต่ -2 × 109 ถึง 2 × 109
ข้อมูลออก
บรรทัดเดียว มีระยะห่างที่น้อยที่สุด ตามด้วยช่องว่าง แล้วตามด้วยจำนวนคู่สถานีที่ห่างกันเท่ากับค่านั้น
6
350 -120 900 410 15 47060 25
8 3 8 3 80 4ดูคำใบ้
เทียบทุกคู่ต้องทำราว 5 × 109 ครั้ง ไม่ทัน ถ้าเรียงแล้ว คู่ที่ใกล้กันที่สุดต้องอยู่ติดกันเสมอ ดูแค่ N - 1 คู่ที่ติดกันพอ มีสามจุดที่ต้องระวัง หนึ่ง ค่าถึง ±2 × 109 ฟังก์ชันเปรียบเทียบของ qsort ห้ามใช้ return x - y ตามหน้า 13.4 สอง ผลต่างอาจถึง 4 × 109 ต้องคำนวณเป็น long long และสาม ถ้าระยะน้อยสุดเป็น 0 สถานีที่เวลาเท่ากัน c สถานีจับคู่กันได้ c × (c - 1) / 2 คู่ ไม่ใช่แค่คู่ที่ติดกัน และจำนวนคู่อาจเกิน int
ดูเฉลย
#include <stdio.h>
#include <stdlib.h>
int when[100000];
int compare_int(const void *p, const void *q)
{
int x = *(const int *)p;
int y = *(const int *)q;
if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &when[i]);
}
qsort(when, n, sizeof(int), compare_int);
long long best = (long long)when[1] - when[0];
for (int i = 2; i < n; i++) {
long long gap = (long long)when[i] - when[i - 1];
if (gap < best) {
best = gap;
}
}
long long pairs = 0;
if (best > 0) {
for (int i = 1; i < n; i++) {
if ((long long)when[i] - when[i - 1] == best) {
pairs++;
}
}
} else {
int start = 0;
for (int i = 1; i <= n; i++) {
if (i == n || when[i] != when[i - 1]) {
long long size = i - start;
pairs += size * (size - 1) / 2;
start = i;
}
}
}
printf("%lld %lld\n", best, pairs);
return 0;
}ข้อ 9 คู่สลับอักษร
ชมรมภาษาอังกฤษจัดเกมสลับอักษร นักเรียนส่งคำมาทั้งหมด N คำ สองคำเป็นคู่สลับอักษร (anagram) ถ้าใช้ตัวอักษรชุดเดียวกัน แต่ละตัวมีจำนวนเท่ากัน แค่เรียงคนละลำดับ เช่น listen กับ silent หรือ stop กับ pots แต่ lose กับ loose ไม่ใช่ เพราะจำนวนตัว o ไม่เท่ากัน คำที่เหมือนกันทุกตัวก็ถือว่าเป็นคู่สลับอักษรกัน
ให้นับว่ามีกี่คู่ (i, j) ที่ i < j และคำที่ i กับคำที่ j เป็นคู่สลับอักษรกัน
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N (1 ≤ N ≤ 100000)
อีก N บรรทัด บรรทัดละหนึ่งคำ แต่ละคำเป็นตัวพิมพ์เล็กภาษาอังกฤษยาว 1 ถึง 8 ตัว
ข้อมูลออก
จำนวนคู่ที่เป็นคู่สลับอักษร
7
listen
google
silent
stop
enlist
pots
tops67
lose
loose
sole
cat
act
tac
dog4ดูคำใบ้
สองคำเป็นคู่สลับอักษรกันก็ต่อเมื่อเรียงตัวอักษรในคำแล้วได้คำเดียวกัน เช่น listen และ silent เรียงแล้วได้ eilnst ทั้งคู่ คำยาวไม่เกิน 8 ตัว เรียงตัวอักษรด้วย insertion sort ได้สบาย จากนั้นเรียงคำที่ได้ทั้งหมดด้วย qsort กับ strcmp แบบหน้า 13.4 คำที่เหมือนกันจะอยู่ติดกัน กลุ่มที่มี c คำจับคู่ได้ c × (c - 1) / 2 คู่ ผลรวมอาจเกิน int
ดูเฉลย
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char key[100000][9];
void sort_letters(char s[])
{
int length = strlen(s);
for (int i = 1; i < length; i++) {
char letter = s[i];
int j = i - 1;
while (j >= 0 && s[j] > letter) {
s[j + 1] = s[j];
j--;
}
s[j + 1] = letter;
}
}
int compare_key(const void *p, const void *q)
{
return strcmp((const char *)p, (const char *)q);
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%s", key[i]);
sort_letters(key[i]);
}
qsort(key, n, sizeof(key[0]), compare_key);
long long pairs = 0;
int start = 0;
for (int i = 1; i <= n; i++) {
if (i == n || strcmp(key[i], key[i - 1]) != 0) {
long long size = i - start;
pairs += size * (size - 1) / 2;
start = i;
}
}
printf("%lld\n", pairs);
return 0;
}ข้อ 10 ต่อบัตรให้ได้เลขมากที่สุด
เกมบัตรตัวเลขมีบัตร N ใบ แต่ละใบเขียนจำนวนเต็มไม่ติดลบไว้หนึ่งจำนวน ผู้เล่นต้องวางบัตรทุกใบเรียงต่อกันเป็นแถวเดียว แล้วอ่านตัวเลขทั้งแถวติดกันเป็นจำนวนเดียว เช่น บัตร 30 5 34 วางเป็น 5 34 30 จะได้ 53430 ให้หาจำนวนที่มากที่สุดที่วางได้
ข้อมูลเข้า
บรรทัดแรกมีจำนวนเต็ม N (1 ≤ N ≤ 100000)
บรรทัดที่สองมีตัวเลขบนบัตร N ใบ คั่นด้วยช่องว่าง แต่ละจำนวนเป็นจำนวนเต็มตั้งแต่ 0 ถึง 109 เขียนโดยไม่มีเลข 0 นำหน้า
ข้อมูลออก
จำนวนที่มากที่สุด พิมพ์โดยไม่มีเลข 0 นำหน้า ถ้าจำนวนนั้นเป็นศูนย์ให้พิมพ์ 0 ตัวเดียว
5
30 5 34 3 995343302
10 2210ดูคำใบ้
ผลยาวได้ถึงล้านหลัก เก็บเป็นตัวเลขไม่ได้ ให้รับบัตรแต่ละใบเป็นสตริง แล้วคิดว่าบัตร a ควรวางก่อนบัตร b เมื่อไร การเรียงตามค่าตัวเลขผิด เพราะ 9 ต้องมาก่อน 30 ส่วนการเรียงตาม strcmp อย่างเดียวก็ผิด ลองบัตร 3 กับ 30 ดู ให้ลองต่อทั้งสองแบบ คือ a ตามด้วย b และ b ตามด้วย a แบบไหนได้มากกว่าก็เลือกแบบนั้น สองแบบยาวเท่ากันจึงเทียบด้วย strcmp ได้เลย เขียนเป็นฟังก์ชันเปรียบเทียบของ qsort ตามหน้า 13.4 แล้วอย่าลืมกรณีที่บัตรเป็น 0 ทุกใบ
ดูเฉลย
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char card[100000][11];
int compare_card(const void *p, const void *q)
{
const char *a = p;
const char *b = q;
char ab[21], ba[21];
strcpy(ab, a);
strcat(ab, b);
strcpy(ba, b);
strcat(ba, a);
return strcmp(ba, ab);
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%s", card[i]);
}
qsort(card, n, sizeof(card[0]), compare_card);
if (strcmp(card[0], "0") == 0) {
printf("0\n");
return 0;
}
for (int i = 0; i < n; i++) {
printf("%s", card[i]);
}
printf("\n");
return 0;
}