დპ ბადეზე

რობოტი საწყობის იატაკზე, პერსონაჟი თამაშის რუკაზე, უიაფესი მარშრუტი ღირებულებების მატრიცაში: როცა მხოლოდ მარჯვნივ ან ქვევით მოძრაობ, ყოველი უჯრის პასუხი სულ ორი მეზობლიდან მოდის.

საშუალო⏱ 10 წთ
01

ისწავლე

იდეა, მექანიზმი და ფასი.

01გზების დათვლა: შეკრიბე ორი უჯრა, საიდანაც მოხვედი

რამდენი გზით შეიძლება ბადის ზედა მარცხენა კუთხიდან ქვედა მარჯვენამდე მისვლა, თუ მხოლოდ მარჯვნივ ან ქვევით ვმოძრაობთ?

(i, j) უჯრაში შემავალი ყოველი გზა ან ზემოდან მოდის, ან მარცხნიდან, და ეს ორი ჯგუფი არ იკვეთება. ამიტომ

ways[i][j] = ways[i−1][j] + ways[i][j−1]

ზედა სტრიქონსა და მარცხენა სვეტს თითო გზა აქვს (სწორი ხაზი): ესაა საბაზისო შემთხვევები. ვავსებთ სტრიქონ-სტრიქონ, მარცხნიდან მარჯვნივ, და ორივე მეზობელი ყოველთვის მზადაა.

4 × 5 ბადეზე კუთხეში 35 გამოდის. შეიძლება პასკალის სამკუთხედი იცანი: პასუხი ბინომიალური კოეფიციენტია C(m+n−2, m−1). მაგრამ ამოცანის შეცვლისას, მაგალითად როცა ზოგი უჯრა დაბლოკილია, მხოლოდ დპ გადარჩება.

რამდენი გზაა, თუ მხოლოდ ქვევით/მარჯვნივ ვმოძრაობთ?1111112345136101514102035ways(i, j) =ways(i−1, j) + ways(i, j−1)ზედა სტრიქონი და მარცხენასვეტი: მხოლოდ 1 გზაკუთხეში: 35 გზა

02უიაფესი გზა: პლუსის ნაცვლად min

ახლა ყოველ უჯრას ღირებულება აქვს და ვეძებთ გზას უმცირესი ჯამით. იგივე ორი მეზობელი, სხვა გაერთიანება:

dp[i][j] = grid[i][j] + min(dp[i−1][j], dp[i][j−1])

სადაც dp[0][0] = grid[0][0], ხოლო პირველი სტრიქონი და სვეტი უბრალოდ დაგროვებული ჯამებია (შესასვლელი მხოლოდ ერთია).

ნახაზის ბადეზე კუთხეში 44 გამოდის. მარშრუტის დასაბეჭდად კუთხიდან ვიწყებთ და ყოველ ჯერზე იმ მეზობელზე გადავდივართ (ზედა ან მარცხენა), რომლის dp უფრო მცირეა, სანამ საწყის უჯრამდე არ მივალთ. ეს ისეთივე უკან სვლაა, როგორიც მონეტებში.

რატომ არ გვჭირდება BFS ან დეიქსტრა? იმიტომ, რომ სვლები მხოლოდ მარჯვნივ ან ქვევითაა, დამოკიდებულებების გრაფი აციკლურია და სტრიქონ-სტრიქონ რიგი უკვე ტოპოლოგიური რიგია. ერთი გავლა, O(R·C), პრიორიტეტული რიგის გარეშე. თუ ზემოთ ან მარცხნივაც შეიძლება სვლა, ციკლები ჩნდება და დეიქსტრა გჭირდება.

ბადე (ღირებულებები)379279835517985386410dp = მინ. ჯამი აქამდე310192128121821263113202934361624303444dp[i][j] = grid[i][j] + min(ზედა, მარცხენა)
მარცხნივ: უჯრების ღირებულება. მარჯვნივ: საუკეთესო ჯამი აქამდე. მწვანე: კუთხიდან აღდგენილი მარშრუტი.

03დაბრკოლებები, მეხსიერება და საერთო ჩონჩხი

ნამდვილ ბადეებს კედლები აქვს. დაბლოკილი უჯრა უბრალოდ იღებს ways = 0-ს (ან dp = ∞-ს ღირებულებების შემთხვევაში), და იგივე წესი მის გარშემო გრძელდება. ყურადღება მიაქციე საბაზისო შემთხვევებს: კედელი პირველ სტრიქონში მის მარჯვნივ ყველა უჯრას ბლოკავს.

მთელი ცხრილი იშვიათად გჭირდება. i-ური სტრიქონი მხოლოდ i−1-ე სტრიქონს და მარცხენა უჯრას კითხულობს, ამიტომ C სიგრძის ერთი მასივი საკმარისია: დასათვლელად row[j] += row[j−1], ღირებულებებისთვის row[j] = grid + min(row[j], row[j−1]). მეხსიერება O(R·C)-დან O(C)-მდე მცირდება.

„ორგანზომილებიანი ცხრილი, სადაც ყოველი უჯრა ზედა, მარცხენა ან დიაგონალური მეზობლიდან ითვლება“ დპ-ის ყველაზე გავრცელებული ფორმაა. მას ზურგჩანთაში, უსქ-სა და რედაქტირების მანძილში შეხვდები; იცვლება მხოლოდ უჯრების მნიშვნელობა და გაერთიანების წესი.

დაბრკოლება = 0 გზა11111✕121124ბლოკირებულ უჯრაში ways = 0,დანარჩენი წესი არ იცვლება.ერთი სტრიქონი საკმარისია:row[j] += row[j−1]მეხსიერება: O(C)

ფასი ერთი შეხედვით

R × C ბადის შევსებაO(R·C)
მეხსიერება ერთი მოძრავი სტრიქონითO(C)
მარშრუტის აღდგენაO(R + C)

დაიმახსოვრე

  1. როცა მხოლოდ მარჯვნივ ან ქვევით ვმოძრაობთ, ყოველი უჯრა ზედა და მარცხენა მეზობელზეა დამოკიდებული: გზების დასათვლელად ვკრებთ, უიაფესისთვის min-ს ვიღებთ.
  2. სტრიქონ-სტრიქონ რიგი ამ აციკლური გრაფის ტოპოლოგიური რიგია, ამიტომ არც რიგი და არც დეიქსტრა არ გვჭირდება.
  3. რადგან სტრიქონი მხოლოდ წინა სტრიქონს კითხულობს, C სიგრძის ერთი მასივი მთელ ცხრილს ცვლის.
02

ითამაშე

გაიარე ალგორითმი ბიჯ-ბიჯ, მერე სცადე შენს მონაცემებზე.

👀 რას უყურო: ყოველი ახალი dp უჯრა მხოლოდ ზემოთ და მარცხნივ იყურება. შევსების შემდეგ მწვანე მარშრუტს კუთხიდან უკან მიჰყევი. სცადე შენი ბადე, მაგ. 1 3 1 / 1 5 1 / 4 2 1.

ინტერაქტიული ვიზუალიზატორიაქ დააწკაპე, მერე space ← →
✎ შენი მონაცემებიმაქს. 5 სტრიქონი × 6 სვეტი, რიცხვები 0–99, მაგ. 1 3 1 / 1 5 1 / 4 2 1.

ბადის ღირებულებები

01234
037927
198355
217985
3386410

dp: მინიმალური ჯამის გზა (მხოლოდ ქვევით/მარჯვნივ)

01234
03····
1·····
2·····
3·····
მინიმალური ჯამის გზა, მხოლოდ მარჯვნივ ან ქვევით მოძრაობით. საწყისი უჯრა dp[0][0] = 3.

ფსევდოკოდი

 1 dp[0][0] = grid[0][0] 2 first row/col: only one way in (forced path) 3 dp[i][j] = grid[i][j] + min(dp[i-1][j], dp[i][j-1]) 4 trace back from the corner along the cheaper predecessor
1 / 1
03

შეამოწმე

სამი კითხვა. აირჩიე პასუხი და ნახე ახსნა.

№1

3 × 3 ბადეზე (მარჯვნივ/ქვევით) რამდენი გზა მიდის ქვედა მარჯვენა კუთხემდე?

№2

გზების დათვლის ბადეში უჯრა (0, 2) კედელია. რას უდრის ways[0][3] და ways[0][4]?

№3

თუ ოთხივე მიმართულებით სვლა დასაშვებია, რომელი მეთოდი იპოვის უიაფეს გზას?

04

ივარჯიშე

რეალური ამოცანები გასამყარებლად, მარტივიდან რთულისკენ.