GRID - editorial

My Approach :
step 1 -> Read the first row as a string and replace all the occurrences of ‘#’ with ‘0’ in that row.

(tmp[j] == '#') ? (tmp[j] = '0') : (tmp[j] = '1');

For remaining rows :
step 2 -> Read the next row and replace all the occurrences of ‘#’ with ‘0’ and for the ‘.’ :
Read the number in above cell (that is in the above row and same column) and increase this number by 1 and put the incremented value in the current cell .

 (tmp[j] == '#') ? (tmp[j] = '0') : (tmp[j] = grid[i-1][j] + 1);

Code for reading grid :

        cin >> tmp;
		
		for(j=0 ; j<n ;j++)
		{
			
			(tmp[j] == '#') ? (tmp[j] = '0') : (tmp[j] = '1');
		}
		
		grid.push_back(tmp);
		
		for(i=1;i<n;i++)
		{	
			cin >> tmp;
			
			for(j=0 ; j<n ;j++)
			{	
				(tmp[j] == '#') ? (tmp[j] = '0') : (tmp[j] = grid[i-1][j] + 1);
			}
			
			grid.push_back(tmp);
		}

Now i will start traversing the grid from first row and i will find the last occurence of ‘0’ in that row. Lets suppose that the last occurrence of ‘0’ is ‘index’ . Now i will start from index+1 and check each column upto column <= n .For each column i will calculate :

grid[n-1][j]-grid[i][j] == n-1-i   

If it is true then (i,j) is a valid position otherwise it is invalid position .
Here is my code for this :

    for(i=0 ; i<n ; i++)
	{
		index = grid[i].find_last_of('0');

		for(j = index+1 ; j<n ; j++)
		{
			if(n-1-i == grid[n-1][j]-grid[i][j])
			{
				count++;
			}
					
		}
	}

But i am getting wrong answer . If anyone one can find where i am doing wrong then please let me know ?

Can you Find Where am i Going Wrong , I have Used The Same Logic As Editorial Only i Checked From Bottom Left to Up right and Top Left to Bottom Right …


#include <iostream>
#include <cstdio>
#include <algorithm>
#define l(x) scanf("%lld",&x);

typedef long long int ll;
using namespace std;
int main() {
	// your code goes here
	ll t;
	ios_base::sync_with_stdio(0);
    l(t);
    getchar();
	while(t--)
	{
	    ll n;
	    l(n);
	    getchar();
	    char a[1000][1000];
	    for(ll i=0;i<n;i++){
	        for(ll j=0;j<n;j++)a[i][j]=getchar_unlocked();
	        getchar_unlocked();
	    }
	    
	    ll hoz=0,ver=0;
	    for(ll i=0;i<n;i++)
	        for(ll j=n-1;j>=0;j--){
	            if(a[i][j]=='.')hoz++;
	            else break;
	    }
	            for(ll j=n-1;j>=0;j--)
	                for(ll i=n-1;i>=0;i--){
	                    if(a[i][j]=='.')ver++;
	                    else break;
	                    
	                }
	        
	       
	   printf("%lld\n",min(hoz,ver));
	    
	}
	return 0;
}

The best way to solve this problem without DP is to keep two arrays, namely row[] and col[] which stores the rightmost and the bottom-most encounter of '#'for each row and column respectively for the whole grid. It is obvious that any ray entering from below cannot pass the barrier ‘#’ than the bottom-most encounter for each column. Similarly, a ray cannot pass the ‘#’ barrier if it comes from the left of the rightmost ‘#’ occurrence.

Hence, each of the ‘.’ in a column above bottom-most '#'and each of the ‘.’ in a row on left of the rightmost ‘#’ will not be suitable place to keep a mirror. So, a suitable place will be the one where a ‘.’ is below the bottom-most ‘#’ for that column and on right of the righmost ‘#’ for that row. Count all such dots.

See my solution here.

1 Like

why i am getting wrong answer…pls help

boolean a[][]=new boolean[n][n];
int count =0;
for(i=0;i<n;i++)
{
String b=in.readLine();
for(j=0;j<n;j++)
if(b.charAt(j)==’.’)
a[i][j]=true;
}

for(i=n-1;i>=0;i–)
{
for(j=n-1;j>=0;j–)
{
if(i!=n-1)
a[i][j]=(a[i][j] && a[i+1][j]);
if(j!=n-1)
a[i][j]=(a[i][j] && a[i][j+1]);

if(a[i][j]==true)
count++;
}
}
ob.println(count);
}

}}

Great explanation

1 Like

Another approach for the solution, could be using binary search. Store the positions of the rocks (“#”) in a vector in a sorted manner and then find if there is a number greater then j in rows[i] and a number greater then i in cols[j], using binary search (when checking if cell (i,j) is possible or not). row[i] is a vector which stores the positions of rocks in ith row in sorted manner and similarly for col[j].

The overall complexity of the solution would be N^2log(N), which is sufficient in this case.

Link to the solution :- CodeChef: Practical coding for everyone

time complexity:O(n^2)

1.from SOUTH - from every column keep marking dots ‘.’ with a different char until you encounter a hash ‘#’ , if you encounter a hash stop moving in that column and do the same in the remaining columns (starting from south) . this can be done in O(n^2) time .
now ,
2.from EAST- keep on moving in a given row until you encounter a hash ‘#’ , and increment your count whenever you encounter that different char (that you set while moving from south ) . do the same in remaining rows . this will take O(n^2) time

the final count will be your answer … ( my solution ran in 0.41 sec., c++ , using scanf/printf )

why it is giving run time error …
https://www.codechef.com/viewsolution/10744547

No need for dynamic programming in this question. Just throw light from east and then from south.
Indexes which recieved light from both east and south will have count 2. Rest will have count 0(initial) or 1(just from 1 side). Blocks are numbered 99.

While throwing light if you occur a 99/block stop the light else continue in that row or column.

At end count all blocks with count==2 and that is the answer. :slight_smile:

1 Like

here is my solution for the above problem in cpp
https://github.com/anjn98/codechef/blob/master/GRID.cpp

My approach was:

  1. Make two NxN arrays
    1. Vertical array (to trace visibility from east)
    2. Horizontal array (to trace visibility from south)
  2. iterate each row from right to left in horizontal array. Mark items which are not visible.
  3. iterate each row from bottom to top in horizontal array and element is called v[i][j]. If v[i][j]=='.' and h[i][j]=='.' then Its a match :)
**Example**: Same example which is given in figure of problem description

Step 1: Horizontal array initially be like

…#…

…#

.##.#

…#.

Vertical array initially be like

…#…

…#

.##.#

…#.

Step 2:
Horizontal array be like
###…

####.

As I cannot see beyond a stone from east

Vertical array be like

…#…

…#

.##.#

…#.

Step 3:
Horizontal array be like

###…

####.

Vertical array be like

.####

.####

.####

.####

…#.

As I cannot see beyond a stone from south

Step 4: Answer will be the count of points which are common in both as ‘.’ Hence answer is 2

My JAVA solution is can be found HERE

No, it was not increased for Ruby. We did not test it for Ruby. So it was not increased.

Its a known fact that both Python and Ruby are similar in performance. In fact Ruby is a little slower. I feel the time limit should have been increased for Ruby too.

1 Like

Really good question. Was so simple but I made it really complex. :frowning:

exactly same approach :slight_smile: and the best approach…
even variable names are also same :slight_smile: :slight_smile:

Is the TL for Python for practice also 8s? I am getting TLE for the 2nd pseudo code mentioned in the editorial.

@nisargshah95: For this problem we tested in python and it was working fine. Though sometimes it happens that things don’t work quite well with python. So either please optimize your solution or please try in other language like C++ or Java.

Ya… DP was not needed… space efficient as well …:slight_smile:

How about array[1][2] element below ?? For that row[1] = false , col[2]= false but it is valid point.

 #.#
 #..  
 #..

How does one see the east keeping the mirror 45*.
The story is not so good :frowning: