Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions MaxRect.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import acm.program.ConsoleProgram;

public class MaxRect extends ConsoleProgram {

private int maxRect(int[][] arr) {
int max = 0;
for (int r = 0; r < arr.length; r++) {
for (int c = 0; c < arr[r].length; c++) {

if (arr[r][c] == 1) {
for (int i = r; i < arr.length; i++) {
for (int j = c; j < arr[i].length; j++) {

if (arr[i][j] == 1) {
if (allOnes(arr, r, c, i, j)) {
if ((i - r + 1) * (j - c + 1) > max) {
max = (i - r + 1) * (j - c + 1);
}
}
}

}
}
}

}
}
return max;
}

private boolean allOnes(int[][] arr, int r, int c, int i, int j) {
for (int k = r; k <= i; k++) {
for (int p = c; p <= j; p++) {
if (arr[k][p] != 1) {
return false;
}
}
}
return true;
}
}
117 changes: 117 additions & 0 deletions MaxRect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# MaxRect

პრობლემა:
```
გადმოგეცემათ nxm-ზე მატრიცა რომელშიც მხოლოდ 0-ები და 1-ები წერია. მეთოდმა
უნდა დააბრუნოს ამ მატრიცის ყველაზე დიდი ქვემართკუთხედის
ზომა(ელემენტების რაოდენობა) რომელიც მხოლოდ 1-ებისგან შედგება.
მაგალითად:

01100100
01111100
00111100
00111100

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

01 1001 00
01*1111*00
00*1111*00
00*1111*00

შესაბამისად ამ მატრიცაზე მეთოდმა უნდა დააბრუნოს 12. ჩათვალეთ რომ
გადმოცემულ მატრიცაში ერთი უჯრა მაინც იქნება რომელშიც წერია 1.

```

## პროლბლემის გააზრება:

* ჩვენ გადმოცემულ მატრიცაში უნდა ვიპოვოთ ისეთი მართკუთხედი, რომელიც შედგენილი იქნება მხოლოდ ერთიანებისაგან, მაგ:
```
111 1 11
111 1 11
```

* ამ ამოცანაში მთავარია მოვიფიქროთ, თუ როგორ ვიპოვოთ ასეთი მართკუთხედები, კოდის დაწერა კი არც ისე რთულია.

## პრობლემის გადაჭრის გზა:

* მე გთავაზობთ შემდეგს:

* გადავუყვეთ მატრიცის თითოეულ ელემენტს და თითოეულისათვის გავაკეთოთ შემდეგი რამ:

* დავიმახსოვროთ მოცემული წერტილი. შემდეგ ამ წერტილიდან მარჯვნივ და ქვემოთ გადავუყვეთ სხვა წერტილებს. ალბათ გაინტერესებთ, თუ რას წარმოადგენენ ეს სხვა წერტილები?! ეს სხვა წერტილები არიან დამახსოვრებული წერტილის მოპირდაპირე წერტილები მართკუთხედში. იხილეთ სურათი: checkForAllPoints.png, რომელშიც განხილულია თუ როგორ ვიქცევით პირველი წერტილისათვის მატრიცაში. ანალოგიური მიდგომაა სხვა წერტილებზეც.

* დამახსოვრებული წერტილი და "ის რაღაც სხვა წერტილი" რომ შევაერთოთ მართკუთხედში მივიღებთ დიაგონალს. ეს ყველაფერი რომ უკეთ წარმოიდგინოთ, ნახეთ სურათი: diagonalPoints.png.

* შემდეგ უნდა შევამოწმოთ არის თუ არა ამ მოცემულ სამკუთხედში სულ ერთიანები. თუ პასუხი არის `true` უნდა შევამოწმოთ ამ მართკუთხედის ფართობი არის თუ არა მეტი მანამდე შემოწმებულ მართკუთხედების ფართობებზე. თუ პასუხი არის `false`, არაფერს ვაკეთებთ და გადავდივართ შემდეგ წერტილზე.

## კოდის რეალიზაცია:

* პირბელ რიგში, შევქმნათ მეთოდი რომელიც გვიბრუნებს მაქსიმალური ფართობის მქონე მართკუთხედის ფართობს, `private int maxRect(int[][] arr)`, რომელსაც გადავცემთ მატრიცას.

* მივყვეთ "პრობლემის გადაჭრის გზაში" მოცემულ ნაბიჯებს და დავწეროთ შესაბამისი კოდი.

* გადავუყვეთ მატრიცის თითოეულ ელემენტს:
```java
for (int r = 0; r < arr.length; r++) {
for (int c = 0; c < arr[r].length; c++) {
```
სადაც r არის შესაბამისი სტრიქონის ნომერი და c არის შესაბამისი სვეტის ნომერი.

* დავიმახსოვროთ მოცემული წერტილი:
```java
if (arr[r][c] == 1) {
```
თუ მოცემული წერტილი 1 ის ტოლი არაა ჩვენ არ გვაინტერესებს ეს წერტილი და გადავდივართ შემდეგ წერტილზე, რადგან რა დიდი მართკუთხედის წერტილიც არ უნდა იყოს ეს წერტილი, ამ მართკუთხედში ყველა ელემენტი 1 ის ტოლი არ გამოვა.

* ვიპოვოთ მეორე წერტილი, რომელიც ამჟამად მყოფი ელემენტის ან მარჯვნივ დგას ან ქვემოთ:
```java
for (int i = r; i < arr.length; i++) {
for (int j = c; j < arr[i].length; j++) {
```
შევამოწმოთ არის თუ არა ეს მეორე წერტილიც 1 ის ტოლი. თუ არაა, მაშინ ჩვენ ამ ორი წერტილით მოჭიმული მართკუთხედიც არ გვაინტერესებს ზემოთხსენებული მიზეზის გამო.

```java
if (arr[i][j] == 1) {
```
სადაც i და j წარმოადგენენ მეორე წერტილისთვის სტრიქონის ნომერს და სვეტის ნომერს.

* შევამოწმოთ არის თუ არა ამ ორი წერტილით მოჭიმულ მართკუთხედში ყველა ერთიანი.
```java
if (allOnes(arr, r, c, i, j)) {
```
მეთოდი, `allOnes(arr, r, c, i, j)`, გადაუყვება ამ ორ წერტილით მოჭიმულ მართკუთხედში ყველა ელემენტს და თუ იპოვის 0 ს აბრუნებს `false`, ხოლო თუ 0 იანი არ გვხვდება, აბრუნებს `true` ს. კოდი საკმაოდ მარტივია:

```java
for (int k = r; k <= i; k++) {
for (int p = c; p <= j; p++) {
if (arr[k][p] != 1) {
return false;
}
}
}
return true;
```
გადაუყვება სტრიქონებს r დან i მდე და სვეტებს c დან j მდე. r <= i, c <= j.

* ახლა უნდა შევამოწმოთ არის თუ არა ეს მართკუთხედი მაქსიმალური ფართობის მქონე.
```java
if ((i - r + 1) * (j - c + 1) > max) {
max = (i - r + 1) * (j - c + 1);
}
```
max არის რაღაც ცვლადი, რომელშიც ვინახავთ მაქსიმალური ფართობის მქონე მართკუთხედის ფართობს.

იმის მიხვედრას თუ როგორ ვიგებთ გვერდებს, ეს საკმაოდ მარტივია. `i - r` და `j - c`. თუმცა გაგიკვირდებათ, თუ რატომ ვუმატებთ თითოეულ გვერდს კიდევ ერთს. რომ წარმოვიდგინოთ მხოლოდ წერტილი და კოდში დაგვეწერა `(i - r) * (j - c)`, პასუხს ამ შემთხვევისათვის მივიღებდით ნულს, როდესაც რეალურად ის ერთის ტოლია. ან რო გვქონოდა წერტილების გვერდიგვერდ, მაშინ პასუხი გამოგვივიდოდა 0 და აშ. ამიტომ ამ ზემოხსენებულ მონაცემებს დამატებით უნდა დავუმატოთ კიდევ ერთი.

### შესაძლო ხარვეზები:

* ერთი ხარვეზი უკვე მოგახსენეთ "კოდის რეალიზაციაში", როდესაც ვისაუბრეთ, თუ რატომ ჭირდებოდა ზემოხსენებულ მონაცემებს ერთის დამატება.

* მეორე ხარვეზი შესაძლოა ყოფილიყო შემდეგი: `(r - i + 1)`, რაც არასწორია რადგან r <= i და ზოგ შემთხვევაში ეს უარყოფით რიცხვს მოგვცემდა, რაც არასწორია. ამის გამოსწორება შეიძლება თუ დავწერთ `(i - r + 1)` ან ავიღებთ სხვაობის მოდულს. ანალოგიურად ვიქცევით სვეტებზეც.

* ზოგმა შეიძლება ჩათვალოს, რომ i > r, რაც არასწორია, რადგან ამით ჩვენ ვუარყოფთ ისეთ მაგალითებს, როგორებიცაა: 1x1, 1x2, 1x5 და აშ. ანალოგიურად სვეტებზეც.

* შემოწმების დროსაც, როდესაც ვამოწმებთ არის თუ არა მოცემულ მართკუთხედში ყველა ერთიანი, ჩვენ უნდა გავითვალისწინოთ ის წერტილებიც, რომლებიც ამ მართკუთხედს ჭიმავენ, რადგან წინააღმდეგ შემთხვევაში ჩვენ ჩავთვლით, რომ ამ წერტილების ზევით, ქვემოთ, და გვერდზე ერთიანები წერია, რაც არასწორია, რადგან ჩვენ მხოლოდ ვიცით, რომ ეს წერტილები არიან მხოლოდ და მხოლოდ ერთიანების ტოლი. სურათი, რომ უკეთ წარმოიდგინოთ, ნახეთ სურათი: errorInCheckingElements.png.
Binary file added checkForAllPoints.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added diagonalPoints.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added errorInCheckingElements.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.