20-dars: Flood fill va panjara
3-darajaOltin — graflar17–24 darslar
Bu darsdan keyin siz
- panjarani graf sifatida ko’rasiz va qo’shnilarni koordinatadan hisoblaysiz
- flood fill bilan komponentalarni sanaysiz
- chekka tekshiruvlarini xatosiz yozasiz
Avval qo’lda
“Avval qo’lda” bo'limiga havolaAvval qo‘lda
Katakli qog’ozda 8 × 8 maydon chizing va taxminan yarim kataklarni bo’yang — bular quruqlik, qolgani suv.
Endi orollarni sanang. Har yangi orolni boshqa rang bilan ustidan bo’yab chiqing: bitta katakdan boshlab, yonma-yon turgan hamma quruqlikka tarqaling.
Nimani sezishingiz kerak
Ikki narsa sezilgan bo’lishi kerak. Birinchisi: diagonal bo’yicha tegib turgan kataklar alohida orol — «yonma-yon» degan so’zni aniq belgilash kerak. Ikkinchisi: bo’yalgan katakka qayta kirilmadi.
Kompyuter yopiq. Bu mashq tugamaguncha kod ochilmaydi.
Panjara ham graf
“Panjara ham graf” bo'limiga havolaflood fillflood fill
Bitta katakdan boshlab, unga bog’langan barcha kataklarni belgilab chiqish. Panjaradagi DFS yoki BFS ning boshqa nomi.
Farq bitta joyda: graf masalasida qo’shnilar ro’yxati saqlanadi, panjarada esa hisoblanadi. To’rt qo’shni koordinatadan chiqadi.
YONALISH = ((-1, 0), (1, 0), (0, -1), (0, 1))y, x = 2, 3for dy, dx in YONALISH: print(y + dy, x + dx)Avval o'ylang: bu kod nima chiqaradi? Ishga tushirishdan oldin yozing.
YONALISH = ((-1, 0), (1, 0), (0, -1), (0, 1))y, x = 2, 3for dy, dx in YONALISH: print(y + dy, x + dx)Haqiqiy natija:
1 3 3 3 2 2 2 4
To'rt yo'nalish: yuqori, past, chap, o'ng. Diagonal kerak bo'lsa ro'yxatga yana to'rtta juftlik qo'shiladi — lekin shart buni aniq aytishi kerak.
Javobni ko'rish
1 3 3 3 2 2 2 4
To'rt yo'nalish: yuqori, past, chap, o'ng. Diagonal kerak bo'lsa ro'yxatga yana to'rtta juftlik qo'shiladi — lekin shart buni aniq aytishi kerak.
Sekin yechim
“Sekin yechim” bo'limiga havolaHar quruqlik katagidan boshlab butun orolni qaytadan kezamiz va topilgan to’plamni saqlaymiz.
xarita = ["##.", "#..", "..#"]r, c = len(xarita), len(xarita[0])orollar = set()for i in range(r): for j in range(c): if xarita[i][j] != "#": continue korilgan = {(i, j)} stek = [(i, j)] while stek: y, x = stek.pop() for dy, dx in ((-1, 0), (1, 0), (0, -1), (0, 1)): ny, nx = y + dy, x + dx if 0 <= ny < r and 0 <= nx < c and xarita[ny][nx] == "#": if (ny, nx) not in korilgan: korilgan.add((ny, nx)) stek.append((ny, nx)) orollar.add(frozenset(korilgan))print(len(orollar))Avval o'ylang: bu kod nima chiqaradi? Ishga tushirishdan oldin yozing.
xarita = ["##.", "#..", "..#"]r, c = len(xarita), len(xarita[0])orollar = set()for i in range(r): for j in range(c): if xarita[i][j] != "#": continue korilgan = {(i, j)} stek = [(i, j)] while stek: y, x = stek.pop() for dy, dx in ((-1, 0), (1, 0), (0, -1), (0, 1)): ny, nx = y + dy, x + dx if 0 <= ny < r and 0 <= nx < c and xarita[ny][nx] == "#": if (ny, nx) not in korilgan: korilgan.add((ny, nx)) stek.append((ny, nx)) orollar.add(frozenset(korilgan))print(len(orollar))Haqiqiy natija:
2
Ikki orol: chap yuqoridagi uchta katak va o'ng pastdagi yolg'iz katak. Ular faqat diagonal bo'yicha tegib turibdi, demak alohida.
Javobni ko'rish
2
Ikki orol: chap yuqoridagi uchta katak va o'ng pastdagi yolg'iz katak. Ular faqat diagonal bo'yicha tegib turibdi, demak alohida.
Nega sekin
“Nega sekin” bo'limiga havolaUch katakli orol uch marta, ming katakli orol ming marta qayta kezib
chiqiladi. Xarita 500 × 500 bo’lishi mumkin — bu 250 ming katak.
Sig‘adimi?
Bir soniyada taxminan 10⁸ oddiy amal bajariladi.
| Yechim | n = 1 000 | n = 250 000 |
|---|---|---|
Har katakdan qayta kezishn^2 | 10⁶sig‘adi | 10¹⁰sig‘maydi |
Bir marta kezishn | 1 000sig‘adi | 250 000sig‘adi |
Yashil — yechim o‘tadi. Sariq — chegarada, konstanta va til muhim bo‘lib qoladi. Qizil — bu yechim bilan bormaydi, boshqasini qidiring.
Tez yechim
“Tez yechim” bo'limiga havolakorilgan butun xarita bo’ylab bitta marta yuritiladi. Yangi orol
faqat hali bo’yalmagan quruqlik katagidan boshlanadi.
xarita = ["##..#", "#..#.", "..###", "#...#"]r, c = len(xarita), len(xarita[0])korilgan = [[False] * c for _ in range(r)]orollar = 0for i in range(r): for j in range(c): if xarita[i][j] != "#" or korilgan[i][j]: continue orollar += 1 korilgan[i][j] = True stek = [(i, j)] while stek: y, x = stek.pop() for dy, dx in ((-1, 0), (1, 0), (0, -1), (0, 1)): ny, nx = y + dy, x + dx if 0 <= ny < r and 0 <= nx < c: if xarita[ny][nx] == "#" and not korilgan[ny][nx]: korilgan[ny][nx] = True stek.append((ny, nx))print(orollar)Avval o'ylang: bu kod nima chiqaradi? Ishga tushirishdan oldin yozing.
xarita = ["##..#", "#..#.", "..###", "#...#"]r, c = len(xarita), len(xarita[0])korilgan = [[False] * c for _ in range(r)]orollar = 0for i in range(r): for j in range(c): if xarita[i][j] != "#" or korilgan[i][j]: continue orollar += 1 korilgan[i][j] = True stek = [(i, j)] while stek: y, x = stek.pop() for dy, dx in ((-1, 0), (1, 0), (0, -1), (0, 1)): ny, nx = y + dy, x + dx if 0 <= ny < r and 0 <= nx < c: if xarita[ny][nx] == "#" and not korilgan[ny][nx]: korilgan[ny][nx] = True stek.append((ny, nx))print(orollar)Haqiqiy natija:
4
To'rtta orol. Har katak aynan bir marta stekka tushadi, demak ish hajmi panjara o'lchamiga proporsional.
Javobni ko'rish
4
To'rtta orol. Har katak aynan bir marta stekka tushadi, demak ish hajmi panjara o'lchamiga proporsional.
Sinab ko’r
“Sinab ko’r” bo'limiga havolaVizualda har yangi orol boshqa rangda bo’yaladi. Katak faqat bir marta ko’rilishini kuzating.
Flood fill — nechta orol
Har yangi orol boshqa rangda bo'yaladi. Katak faqat bir marta ko'riladi.
Har bo'yalmagan quruqlik katagidan boshlab butun bog'langan bo'lak to'lg'aziladi; necha marta boshlangan bo'lsa — shuncha orol.
Algoritmning har qadami quyidagi ro‘yxatda matn sifatida ham berilgan — vizual faqat shu qadamlarni chizadi, yangi ma’lumot qo‘shmaydi.
- To'q kataklar — quruqlik. Yonma-yon turganlari bitta orol. Diagonal bo'yicha tegib turish yetarli emas.
- Yangi orol topildi — 1-orol. (0, 0) katagidan to'lg'azishni boshlaymiz.
- (0, 0) dan (1, 0), (0, 1) katagi shu orolga qo'shildi.
- Yangi orol topildi — 2-orol. (0, 4) katagidan to'lg'azishni boshlaymiz.
- Yangi orol topildi — 3-orol. (1, 3) katagidan to'lg'azishni boshlaymiz.
- (1, 3) dan (2, 3) katagi shu orolga qo'shildi.
- (2, 3) dan (2, 2), (2, 4) katagi shu orolga qo'shildi.
- (2, 4) dan (3, 4) katagi shu orolga qo'shildi.
- Yangi orol topildi — 4-orol. (3, 0) katagidan to'lg'azishni boshlaymiz.
- Jami 4 ta orol. Har katak ANIQ BIR MARTA ko'rildi — 10 amal, panjara o'lchamiga proporsional.
To'q kataklar — quruqlik. Yonma-yon turganlari bitta orol. Diagonal bo'yicha tegib turish yetarli emas.
Bo'yalgan katak0
Xatoni toping
“Xatoni toping” bo'limiga havolaTuzoq — xatoni toping
20 / 40
Masala500 x 500 panjarada orollar sonini toping.
Taklif qilingan yechim
Bu javobning 3-qismi noto'g'ri. Rekursiv flood fill 500 x 500 panjarada RecursionError beradi: butunlay quruqlik bo'lgan xaritada chuqurlik 250 mingga yetadi, Python chegarasi esa ming atrofida. Mantiq to'g'ri, lekin yechim ishga tushmaydi. To'g'risi: rekursiya o'rniga stek yoki navbat.
Javobning qaysi qismi noto'g'ri? Bosib belgilang.
Rekursiv flood fill 500 x 500 panjarada RecursionError beradi: butunlay quruqlik bo'lgan xaritada chuqurlik 250 mingga yetadi, Python chegarasi esa ming atrofida. Mantiq to'g'ri, lekin yechim ishga tushmaydi. To'g'risi: rekursiya o'rniga stek yoki navbat.
Diqqat qiling: bu xato eng katta testda chiqadi va u odatda oxirgi test bo’ladi. Kichik xaritalarda kod mukammal ishlaydi, shuning uchun muammo topshirilgandan keyin ma’lum bo’ladi.
O’zingizni sinang
“O’zingizni sinang” bo'limiga havola1Panjarada qo'shnilar qanday topiladi?
Javobni ko'rish
Koordinatadan hisoblanadi: (y-1, x), (y+1, x), (y, x-1),
(y, x+1). Qo’shnilar ro’yxati saqlanmaydi.
2Nega avval chegara, keyin katak qiymati tekshiriladi?
Javobni ko'rish
Teskari tartibda xarita[ny][nx] panjaradan tashqarida chaqiriladi.
Python manfiy indeksni oxiridan sanaydi, shuning uchun xato ham
chiqmasligi va jimgina noto’g’ri javob berishi mumkin.
3Diagonal qo'shnilar hisobga olinadimi?
Javobni ko'rish
Faqat shart shuni aytsa. Sukut bo’yicha to’rt yo’nalish olinadi; sakkiz yo’nalish kerak bo’lsa ro’yxatga yana to’rtta juftlik qo’shiladi va javob butunlay o’zgarishi mumkin.
4Bu dars 18-dars bilan qanday bog'liq?
Javobni ko'rish
Bir xil masala: bog’langan guruhlarni sanash. Farqi faqat qo’shnilar saqlanadimi yoki hisoblanadimi degan joyda.
5Flood fill uchun stek va navbat orasida farq bormi?
Javobni ko'rish
Natijada yo’q — ikkalasi ham butun komponentani topadi. Farq faqat kezish tartibida. Eng qisqa masofa kerak bo’lsa navbat majburiy (19-dars).
Masalalar
“Masalalar” bo'limiga havolaMasalalar
3 ta
- Counting RoomsCSES 1192oson
Darsdagi masalaning o‘zi. Rekursiyadan foydalanmang.
- Igor In the MuseumCodeforces 598Do'rta
Har xona uchun javobni BIR MARTA hisoblang va xonadagi hamma katakka bir xil javobni bering.
- MazeCodeforces 377Aqiyin
Teskari o‘ylang: devor qo‘yish o‘rniga, qolishi kerak bo‘lgan kataklarni kezib belgilang.
Lokal mashq: mashqlar/20-orollar/ — masala matni, testlar va tekshir.py. Avval sekin.py ni o‘zingiz yozing, keyin tayyorini oching.
Topshiriq
“Topshiriq” bo'limiga havolaTopshiriq — darajangizni tanlang
Asos · 5–7-sinf — Vizual va aniq ko'rsatmali
Katakli qog’ozda 8 × 8 xarita chizing va orollarni qo’lda bo’yab sanang. Keyin diagonal ham qo’shni deb hisoblab qayta sanang — javob qanday o’zgardi?
Mustahkam · 8–9-sinf — Matnli masala, o'zingiz tuzasiz
20-orollar masalasini yeching. Chegara holatlarini sinang:
butunlay suv, butunlay quruqlik, 1 × 1 xarita.
Chuqur · 10–11-sinf — Algoritmik, chegara holatlari bilan
Masalani kengaytiring: eng katta orol nechta katakdan iborat va u qayerda boshlanadi? Keyin yana bir savol qo’shing — orollar ichida «ko’l» (quruqlik bilan o’ralgan suv) bormi va uni qanday aniqlaysiz?
Darsni belgilash uchun JavaScript kerak. Bu progressni saqlash uchun ishlatiladi — darslikning o'zi JavaScript'siz ham to'liq o'qiladi.