There is a one-dimensional garden of length N. In each position of the N length garden, a fountain has been installed. Given an array a[]such that a[i] describes the coverage limit of ith fountain. A fountain can cover the range from the position max(i – a[i], 1) to min(i + a[i], N). In beginning, all the fountains are switched off. The task is to find the minimum number of fountains needed to be activated such that the whole N-length garden can be covered by water.
Examples:
Input: a[] = {1, 2, 1}
Output: 1
Explanation:
For position 1: a[1] = 1, range = 1 to 2
For position 2: a[2] = 2, range = 1 to 3
For position 3: a[3] = 1, range = 2 to 3
Therefore, the fountain at position a[2] covers the whole garden.
Therefore, the required output is 1.
Input: a[] = {2, 1, 1, 2, 1}
Output: 2
Approach: The problem can be solved using Dynamic Programming. Follow the steps below to solve the problem:
- traverse the array and for every array index, i.e. ith fountain, find the leftmost fountain up to which the current fountain covers.
- Then, find the rightmost fountain that the leftmost fountain obtained in the above step covers up to and update it in the dp[] array.
- Initialize a variable cntFount to store the minimum number of fountains that need to be activated.
- Now, traverse the dp[] array and keep activating the fountains from the left that covers maximum fountains currently on the right and increment cntFount by 1. Finally, print cntFount as the required answer.
Below is the implementation of the above approach.
C++14
#include <bits/stdc++.h>
using namespace std;
int minCntFoun( int a[], int N)
{
int dp[N];
for ( int i=0;i<N;i++){
dp[i]=-1;
}
int idxLeft;
int idxRight;
for ( int i = 0; i < N; i++) {
idxLeft = max(i - a[i], 0);
idxRight = min(i + (a[i] + 1), N);
dp[idxLeft] = max(dp[idxLeft],
idxRight);
}
int cntfount = 1;
idxRight = dp[0];
int idxNext=-1;
for ( int i = 0; i < N; i++)
{
idxNext = max(idxNext,
dp[i]);
if (i == idxRight)
{
cntfount++;
idxRight = idxNext;
}
}
return cntfount;
}
int main()
{
int a[] = { 1, 2, 1 };
int N = sizeof (a) / sizeof (a[0]);
cout << minCntFoun(a, N);
}
|
Java
import java.util.*;
class GFG {
static int minCntFoun( int a[], int N)
{
int [] dp = new int [N];
for ( int i= 0 ;i<N;i++)
{
dp[i]=- 1 ;
}
int idxLeft;
int idxRight;
for ( int i = 0 ; i < N; i++)
{
idxLeft = Math.max(i - a[i], 0 );
idxRight = Math.min(i + (a[i] + 1 ), N);
dp[idxLeft] = Math.max(dp[idxLeft],
idxRight);
}
int cntfount = 1 ;
int idxNext = 0 ;
idxRight = dp[ 0 ];
for ( int i = 0 ; i < N; i++)
{
idxNext = Math.max(idxNext, dp[i]);
if (i == idxRight)
{
cntfount++;
idxRight = idxNext;
}
}
return cntfount;
}
public static void main(String[] args)
{
int a[] = { 1 , 2 , 1 };
int N = a.length;
System.out.print(minCntFoun(a, N));
}
}
|
Python3
def minCntFoun(a, N):
dp = [ 0 ] * N
for i in range (N):
dp[i] = - 1
for i in range (N):
idxLeft = max (i - a[i], 0 )
idxRight = min (i + (a[i] + 1 ), N)
dp[idxLeft] = max (dp[idxLeft],
idxRight)
cntfount = 1
idxRight = dp[ 0 ]
idxNext = 0
for i in range (N):
idxNext = max (idxNext,
dp[i])
if (i = = idxRight):
cntfount + = 1
idxRight = idxNext
return cntfount
if __name__ = = '__main__' :
a = [ 1 , 2 , 1 ]
N = len (a)
print (minCntFoun(a, N))
|
C#
using System;
class GFG {
static int minCntFoun( int [] a, int N)
{
int [] dp = new int [N];
for ( int i = 0; i < N; i++)
{
dp[i] = -1;
}
int idxLeft;
int idxRight;
for ( int i = 0; i < N; i++) {
idxLeft = Math.Max(i - a[i], 0);
idxRight = Math.Min(i + (a[i] + 1),
N);
dp[idxLeft] = Math.Max(dp[idxLeft],
idxRight);
}
int cntfount = 1;
int idxNext = 0;
idxRight = dp[0];
for ( int i = 0; i < N; i++)
{
idxNext = Math.Max(idxNext, dp[i]);
if (i == idxRight)
{
cntfount++;
idxRight = idxNext;
}
}
return cntfount;
}
public static void Main(String[] args)
{
int [] a = { 1, 2, 1 };
int N = a.Length;
Console.Write(minCntFoun(a, N));
}
}
|
Javascript
<script>
function minCntFoun(a, N)
{
let dp = [];
for (let i = 0; i < N; i++)
{
dp[i] = -1;
}
let idxLeft;
let idxRight;
for (let i = 0; i < N; i++)
{
idxLeft = Math.max(i - a[i], 0);
idxRight = Math.min(i + (a[i] + 1), N);
dp[idxLeft] = Math.max(dp[idxLeft],
idxRight);
}
let cntfount = 1;
let idxNext = 0;
idxRight = dp[0];
for (let i = 0; i < N; i++)
{
idxNext = Math.max(idxNext, dp[i]);
if (i == idxRight)
{
cntfount++;
idxRight = idxNext;
}
}
return cntfount;
}
let a = [ 1, 2, 1 ];
let N = a.length;
document.write(minCntFoun(a, N));
</script>
|
Time Complexity: O(N)
Auxiliary Space: O(N)
Brute Force in python:
Approach:
The brute force approach involves checking all possible combinations of fountains that can be activated to cover the entire garden. For each combination, we check if it covers the entire garden and keep track of the minimum number of fountains required.
Initialize the minimum number of fountains to a very large number.
Use a loop to iterate over all possible combinations of fountains that can be activated.
For each combination, check if it covers the entire garden using a helper function is_covered.
If it does, update the minimum number of fountains required.
Return the minimum number of fountains required.
C++
#include <iostream>
#include <vector>
#include <algorithm> // Add this header for std::all_of
#include <limits> // Add this header for std::numeric_limits
bool isCovered( const std::vector< int >& activated, const std::vector< int >& fountains) {
int n = fountains.size();
std::vector< int > coverage(n, 0);
for ( int i : activated) {
int left = std::max(0, i - fountains[i]);
int right = std::min(n - 1, i + fountains[i]);
for ( int j = left; j <= right; j++) {
coverage[j] = 1;
}
}
return std::all_of(coverage.begin(), coverage.end(), []( int val) { return val == 1; });
}
int activateFountains( const std::vector< int >& fountains) {
int n = fountains.size();
int minFountains = std::numeric_limits< int >::max();
for ( int i = 1; i < (1 << n); i++) {
std::vector< int > activated;
for ( int j = 0; j < n; j++) {
if ((i >> j) & 1) {
activated.push_back(j);
}
}
if (isCovered(activated, fountains)) {
minFountains = std::min(minFountains, static_cast < int >(activated.size()));
}
}
return minFountains;
}
int main() {
std::vector< int > a1 = {1, 2, 1};
std::vector< int > a2 = {2, 1, 1, 2, 1};
std::cout << activateFountains(a1) << std::endl;
std::cout << activateFountains(a2) << std::endl;
return 0;
}
|
Java
import java.util.ArrayList;
import java.util.List;
public class FountainActivation {
public static boolean isCovered(List<Integer> activated, List<Integer> fountains) {
int n = fountains.size();
List<Integer> coverage = new ArrayList<>(n);
for ( int i = 0 ; i < n; i++) {
coverage.add( 0 );
}
for ( int i : activated) {
int left = Math.max( 0 , i - fountains.get(i));
int right = Math.min(n - 1 , i + fountains.get(i));
for ( int j = left; j <= right; j++) {
coverage.set(j, 1 );
}
}
return coverage.stream().allMatch(val -> val == 1 );
}
public static int activateFountains(List<Integer> fountains) {
int n = fountains.size();
int minFountains = Integer.MAX_VALUE;
for ( int i = 1 ; i < ( 1 << n); i++) {
List<Integer> activated = new ArrayList<>();
for ( int j = 0 ; j < n; j++) {
if ((i >> j & 1 ) == 1 ) {
activated.add(j);
}
}
if (isCovered(activated, fountains)) {
minFountains = Math.min(minFountains, activated.size());
}
}
return minFountains;
}
public static void main(String[] args) {
List<Integer> a1 = List.of( 1 , 2 , 1 );
List<Integer> a2 = List.of( 2 , 1 , 1 , 2 , 1 );
System.out.println(activateFountains(a1));
System.out.println(activateFountains(a2));
}
}
|
Python3
def activate_fountains(fountains):
n = len (fountains)
min_fountains = float ( 'inf' )
for i in range ( 1 , 2 * * n):
activated = []
for j in range (n):
if (i >> j) & 1 :
activated.append(j)
if is_covered(activated, fountains):
min_fountains = min (min_fountains, len (activated))
return min_fountains
def is_covered(activated, fountains):
n = len (fountains)
coverage = [ 0 ] * n
for i in activated:
left = max ( 0 , i - fountains[i])
right = min (n - 1 , i + fountains[i])
for j in range (left, right + 1 ):
coverage[j] = 1
return all (coverage)
a1 = [ 1 , 2 , 1 ]
a2 = [ 2 , 1 , 1 , 2 , 1 ]
print (activate_fountains(a1))
print (activate_fountains(a2))
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
class FountainActivation {
static bool IsCovered(List< int > activated,
List< int > fountains)
{
int n = fountains.Count;
List< int > coverage
= Enumerable.Repeat(0, n).ToList();
foreach ( int i in activated)
{
int left = Math.Max(0, i - fountains[i]);
int right = Math.Min(n - 1, i + fountains[i]);
for ( int j = left; j <= right; j++) {
coverage[j] = 1;
}
}
return coverage.All(val = > val == 1);
}
static int ActivateFountains(List< int > fountains)
{
int n = fountains.Count;
int minFountains = int .MaxValue;
for ( int i = 1; i < (1 << n); i++) {
List< int > activated = new List< int >();
for ( int j = 0; j < n; j++) {
if ((i >> j & 1) == 1) {
activated.Add(j);
}
}
if (IsCovered(activated, fountains)) {
minFountains = Math.Min(minFountains,
activated.Count);
}
}
return minFountains;
}
static void Main()
{
List< int > a1 = new List< int >{ 1, 2, 1 };
List< int > a2 = new List< int >{ 2, 1, 1, 2, 1 };
Console.WriteLine(
ActivateFountains(a1));
Console.WriteLine(
ActivateFountains(a2));
}
}
|
Javascript
function isCovered(activated, fountains) {
const n = fountains.length;
const coverage = Array(n).fill(0);
for (const i of activated) {
const left = Math.max(0, i - fountains[i]);
const right = Math.min(n - 1, i + fountains[i]);
for (let j = left; j <= right; j++) {
coverage[j] = 1;
}
}
return coverage.every(val => val === 1);
}
function activateFountains(fountains) {
const n = fountains.length;
let minFountains = Infinity;
for (let i = 1; i < (1 << n); i++) {
const activated = [];
for (let j = 0; j < n; j++) {
if ((i >> j & 1) === 1) {
activated.push(j);
}
}
if (isCovered(activated, fountains)) {
minFountains = Math.min(minFountains, activated.length);
}
}
return minFountains;
}
const a1 = [1, 2, 1];
const a2 = [2, 1, 1, 2, 1];
console.log(activateFountains(a1));
console.log(activateFountains(a2));
|
The time complexity of this approach is O(2^n) where n is the number of fountains
the space complexity is O(n).
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
27 Nov, 2023
Like Article
Save Article