Open In App

Count of possible seating arrangements in Cinema hall to maintain Social Distancing

Last Updated : 29 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

In the COVID times, a movie theatre has to follow a Social distance rule where every two seated individuals must have at least 6 feet distance between them. 

Given a list of N non-negative integers where list[k] is the distance between kth seat and (k + 1)th seat and a single row has (N+1) seats. Find out the number of valid seating arrangements. An arrangement without any people seated is also valid.

Examples:

Input: list = {5, 2, 4, 1, 2} 
Output: 16
Explanation: As per the given list the seats are arranged as:
S1 <–5–> S2 <–2–> S3 <–4–> S4 <–1–> S5 <–2–> S6
This has 16 possible seating arrangements
These are the valid combinations (1 means taken):
000000 101000 000010 100001
100000 000100 100010 010001
010000 100100 010010 001001
001000 010100 000001 101001

Input: list =  {8, 10, 16}
Output: 16
Explanation: This has 16 possible seating arrangements
Every combination is a valid combination. Four seats => 2^4 combinations.

 

Naive approach: The naive approach is to use backtracking. At each given seat, there are two choices, sit or do not sit. Visit all the possible arrangements and find the valid solutions. Follow the steps mentioned below:

  • Start from the first seat.
  • For each seat check if the distance from the previous seat is valid or not.
  • If not valid, move to the next seat.
  • If valid then there are two possibilities, either sit or do not sit. Use both the options and move to the next seat.
  • Use these criteria recursively for all the seats.
  • The total number of arrangements found at the end is the required answer.

Below is the implementation of the above approach.

Python3




# Python program to implement the approach
 
# Function to count all valid arrangements
def get_possible_seatings(seats):
     
    # Account for the last seat
    seats.append(0)
    arrangement = []
    total_seatings = 0
    dist = 6
 
    # Function for backtracking
    def dfs(curr, prev_dist):
        nonlocal total_seatings
        if curr > len(seats):
            return
 
        if curr == len(seats):
             
            # This arrangement possible
            total_seatings += 1
            return
 
        # Have only one choice, don't sit
        if prev_dist < dist:
            dfs(curr+1, prev_dist+seats[curr])
        else:
             
            # Have 2 choices here
            arrangement.append(curr)
             
            # Sit here
            dfs(curr+1, seats[curr])
            arrangement.pop(-1)
             
            # Don't sit here
            dfs(curr+1, prev_dist+seats[curr])
        return
 
    # Loop to implement backtracking
    # and call the dfs function
    for index in range(len(seats)):
        arrangement.clear()
        arrangement.append(index)
        dfs(index + 1, seats[index])
 
    # Account for no seats occupied
    return total_seatings + 1
 
# Driver code
if __name__ == "__main__":
    list = [5, 2, 4, 1, 2]
    ans = get_possible_seatings(list)
    print(ans)


Javascript




<script>
 
// JavaScript program to implement the approach
 
// Function to count all valid arrangements
function get_possible_seatings(seats){
     
    // Account for the last seat
    seats.push(0)
    arrangement = []
    total_seatings = 0
    dist = 6
 
    // Function for backtracking
    function dfs(curr, prev_dist){
         
        if(curr > seats.length)
            return
 
        if(curr == seats.length){
             
            // This arrangement possible
            total_seatings += 1
            return
        }
 
        // Have only one choice, don't sit
        if(prev_dist < dist)
            dfs(curr+1, prev_dist+seats[curr])
        else{
             
            // Have 2 choices here
            arrangement.push(curr)
             
            // Sit here
            dfs(curr+1, seats[curr])
            arrangement.pop(-1)
             
            // Don't sit here
            dfs(curr+1, prev_dist+seats[curr])
        }
        return
    }
 
    // Loop to implement backtracking
    // and call the dfs function
    for(let index=0;index<seats.length;index++){
        arrangement = []
        arrangement.push(index)
        dfs(index + 1, seats[index])
    }
 
    // Account for no seats occupied
    return total_seatings + 1
}
 
// Driver code
 
list = [5, 2, 4, 1, 2]
ans = get_possible_seatings(list)
document.write(ans)
 
// This code is contributed by shinjanpatra
 
</script>


C++14




// C++ program to implement the approach
 
#include <iostream>
#include <vector>
 
using namespace std;
 
// Function for backtracking
void dfs(int curr, int prev_dist, vector<int> &arrangement, vector<int> &seats, int &dist, int &total_seatings)
{
    if (curr > seats.size()) {
        return;
    }
 
    if (curr == seats.size()) {
        // This arrangement is possible
        total_seatings += 1;
        return;
    }
 
    // Have only one choice, don't sit
    if (prev_dist < dist) {
        dfs(curr + 1, prev_dist + seats[curr], arrangement, seats, dist, total_seatings);
    }
    else {
        // Have 2 choices here
        arrangement.push_back(curr);
 
        // Sit here
        dfs(curr + 1, seats[curr], arrangement, seats, dist, total_seatings);
 
        arrangement.pop_back();
 
        // Don't sit here
        dfs(curr + 1, prev_dist + seats[curr], arrangement, seats, dist, total_seatings);
    }
 
    return;
}
 
// Function to count all valid arrangements
int get_possible_seatings(vector<int>& seats)
{
 
    // Account for the last seat
    seats.push_back(0);
    vector<int> arrangement;
    int total_seatings = 0;
    int dist = 6;
 
    // Loop to implement backtracking
    // and call the dfs function
    for (int index = 0; index < seats.size(); index++) {
        arrangement.clear();
        arrangement.push_back(index);
        dfs(index + 1, seats[index], arrangement, seats, dist, total_seatings);
    }
 
    // Account for no seats occupied
    return total_seatings + 1;
}
 
// Driver code
int main()
{
    vector<int> seats = { 5, 2, 4, 1, 2 };
    int ans = get_possible_seatings(seats);
    cout << ans << endl;
    return 0;
}


Java




// Java program to implement the approach
 
import java.util.ArrayList;
 
public class Main {
    // Function for backtracking
    public static void dfs(int curr, int prev_dist,
                           ArrayList<Integer> arrangement,
                           ArrayList<Integer> seats,
                           int dist, int[] total_seatings)
    {
        if (curr > seats.size()) {
            return;
        }
 
        if (curr == seats.size()) {
            // This arrangement is possible
            total_seatings[0] += 1;
            return;
        }
 
        // Have only one choice, don't sit
        if (prev_dist < dist) {
            dfs(curr + 1, prev_dist + seats.get(curr),
                arrangement, seats, dist, total_seatings);
        }
        else {
            // Have 2 choices here
            arrangement.add(curr);
 
            // Sit here
            dfs(curr + 1, seats.get(curr), arrangement,
                seats, dist, total_seatings);
 
            arrangement.remove(arrangement.size() - 1);
 
            // Don't sit here
            dfs(curr + 1, prev_dist + seats.get(curr),
                arrangement, seats, dist, total_seatings);
        }
 
        return;
    }
 
    // Function to count all valid arrangements
    public static int
    get_possible_seatings(ArrayList<Integer> seats)
    {
 
        // Account for the last seat
        seats.add(0);
        ArrayList<Integer> arrangement
            = new ArrayList<Integer>();
        int[] total_seatings = { 0 };
        int dist = 6;
 
        // Loop to implement backtracking
        // and call the dfs function
        for (int index = 0; index < seats.size(); index++) {
            arrangement.clear();
            arrangement.add(index);
            dfs(index + 1, seats.get(index), arrangement,
                seats, dist, total_seatings);
        }
 
        // Account for no seats occupied
        return total_seatings[0] + 1;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        ArrayList<Integer> seats = new ArrayList<Integer>();
        seats.add(5);
        seats.add(2);
        seats.add(4);
        seats.add(1);
        seats.add(2);
        int ans = get_possible_seatings(seats);
        System.out.println(ans);
    }
}


C#




// C# program to implement the approach
 
using System;
using System.Collections.Generic;
 
public class Program {
    // Function for backtracking
    static void dfs(int curr, int prev_dist,
                    List<int> arrangement, List<int> seats,
                    ref int dist, ref int total_seatings)
    {
        if (curr > seats.Count) {
            return;
        }
 
        if (curr == seats.Count) {
            // This arrangement is possible
            total_seatings += 1;
            return;
        }
 
        // Have only one choice, don't sit
        if (prev_dist < dist) {
            dfs(curr + 1, prev_dist + seats[curr],
                arrangement, seats, ref dist,
                ref total_seatings);
        }
        else {
            // Have 2 choices here
            arrangement.Add(curr);
 
            // Sit here
            dfs(curr + 1, seats[curr], arrangement, seats,
                ref dist, ref total_seatings);
 
            arrangement.RemoveAt(arrangement.Count - 1);
 
            // Don't sit here
            dfs(curr + 1, prev_dist + seats[curr],
                arrangement, seats, ref dist,
                ref total_seatings);
        }
 
        return;
    }
 
    // Function to count all valid arrangements
    static int get_possible_seatings(List<int> seats)
    {
        // Account for the last seat
        seats.Add(0);
        List<int> arrangement = new List<int>();
        int total_seatings = 0;
        int dist = 6;
 
        // Loop to implement backtracking
        // and call the dfs function
        for (int index = 0; index < seats.Count; index++) {
            arrangement.Clear();
            arrangement.Add(index);
            dfs(index + 1, seats[index], arrangement, seats,
                ref dist, ref total_seatings);
        }
 
        // Account for no seats occupied
        return total_seatings + 1;
    }
 
    // Driver code
    static void Main(string[] args)
    {
        List<int> seats = new List<int>{ 5, 2, 4, 1, 2 };
        int ans = get_possible_seatings(seats);
        Console.WriteLine(ans);
    }
}


Output

16

 
 

Output

16

 

Time Complexity: O(2N)
Auxiliary Space: O(N)

 

Efficient Approach: An efficient approach is to use dynamic programming. Use a dp[] array to store the possible seating arrangements up to the ith seat. Check each of the seat starting from 1st. If the distance between current seat ‘i’ and previous seat ‘j’ is valid (>= 6), add dp[j] to dp[i]. This basically means that both the previous seat and current seat can be occupied together. The total number of ways to sit will increase by the number of ways to be seated at the previous seat. Follow the steps mentioned below:

 

  • Start iterating from the first seat.
  • For each seat check if the distance from the previously occupied seat is valid or not.
  • If valid then increment the number of possible arrangements by the arrangements of the previously occupied seat.
  • If not keep the arrangements unchanged and move to the next seat.
  • The final value at the last seat is the required answer.

 

Below is the implementation of the above approach.

 

C++




// C++ program to implement the approach
#include <bits/stdc++.h>
using namespace std;
 
// sum function
int sum(vector<int>& v)
{
    int res = 0;
    for (auto dt : v)
        res += dt;
    return res;
}
 
// Function to count all valid arrangements
int get_possible_seatings(vector<int>& seats)
{
    int dist = 6;
 
    // Account for the last seat
    seats.push_back(0);
 
    // Each seat can be occupied individually
    vector<int> dp(seats.size(), 1);
 
    // Keep track of total distance
    // from first seat
    vector<int> total_distance(seats.size(), 0);
    int prefix_sum = seats[0];
    for (int index = 1; index < seats.size(); ++index) {
        total_distance[index] = prefix_sum;
        prefix_sum += seats[index];
    }
 
    // Start from second seat onwards,
    // this is the curr seat 'i'
    for (int i = 1; i < seats.size(); ++i) {
        for (int j = 0; j < i; ++j) {
            if (total_distance[i] - total_distance[j]
                >= dist)
                dp[i] += dp[j];
        }
    }
 
    // Account for no seat occupied
    return sum(dp) + 1;
}
 
// Driver code
int main()
{
    vector<int> list{ 5, 2, 4, 1, 2 };
    int ans = get_possible_seatings(list);
    cout << (ans);
 
    return 0;
}
 
    // This code is contributed by rakeshsahni


Java




// Java program for the above approach
import java.util.*;
class GFG
{
 
  // sum function
  static int sum(int[] v)
  {
    int res = 0;
    for (int i = 0; i < v.length; i++)
      res += v[i];
    return res;
  }
 
  // Function to count all valid arrangements
  static int get_possible_seatings(ArrayList<Integer> seats)
  {
    int dist = 6;
 
    // Account for the last seat
    seats.add(0);
 
    // Each seat can be occupied individually
    int[] dp = new int[seats.size()];
    for (int i = 0; i < seats.size(); i++) {
      dp[i] = 1;
    }
 
    // Keep track of total distance
    // from first seat
    int[] total_distance = new int[seats.size()];
    for (int i = 0; i < seats.size(); i++) {
      total_distance[i] = 0;
    }
 
    int prefix_sum = (int)seats.get(0);
    for (int index = 1; index < seats.size(); ++index) {
      total_distance[index] = prefix_sum;
      prefix_sum += (int)seats.get(index) ;
    }
 
    // Start from second seat onwards,
    // this is the curr seat 'i'
    for (int i = 1; i < seats.size(); ++i) {
      for (int j = 0; j < i; ++j) {
        if (total_distance[i] - total_distance[j]
            >= dist)
          dp[i] += dp[j];
      }
    }
 
    // Account for no seat occupied
    return sum(dp) + 1;
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    ArrayList<Integer> list = new ArrayList<Integer>();
 
    list.add(5);
    list.add(2);
    list.add(4);
    list.add(1);
    list.add(2);
 
    int ans = get_possible_seatings(list);
    System.out.print(ans);
  }
}
 
// This code is contributed by sanjoy_62.


Python3




# Python program to implement the approach
 
# Function to count all valid arrangements
def get_possible_seatings(seats):  
    dist = 6
     
    # Account for the last seat
    seats.append(0)
 
    # Each seat can be occupied individually
    dp = [1] * len(seats)
 
    # Keep track of total distance
    # from first seat
    total_distance = [0] * len(seats)
    prefix_sum = seats[0]
    for index, i in enumerate(seats[1:], 1):
        total_distance[index] = prefix_sum
        prefix_sum += i
 
    # Start from second seat onwards,
    # this is the curr seat 'i'
    for i in range(1, len(seats)):
        for j in range(i):
            if total_distance[i] \
            - total_distance[j] >= dist:
                dp[i] += dp[j]
 
    # Account for no seat occupied
    return sum(dp) + 1
 
# Driver code
if __name__ == "__main__":
    list = [5, 2, 4, 1, 2]
    ans = get_possible_seatings(list)
    print(ans)


C#




// C# program to implement the approach
using System;
using System.Collections;
 
class GFG {
 
  // sum function
  static int sum(int[] v)
  {
    int res = 0;
    for (int i = 0; i < v.Length; i++)
      res += v[i];
    return res;
  }
 
  // Function to count all valid arrangements
  static int get_possible_seatings(ArrayList seats)
  {
    int dist = 6;
 
    // Account for the last seat
    seats.Add(0);
 
    // Each seat can be occupied individually
    int[] dp = new int[seats.Count];
    for (int i = 0; i < seats.Count; i++) {
      dp[i] = 1;
    }
 
    // Keep track of total distance
    // from first seat
    int[] total_distance = new int[seats.Count];
    for (int i = 0; i < seats.Count; i++) {
      total_distance[i] = 0;
    }
 
    int prefix_sum = (int)seats[0];
    for (int index = 1; index < seats.Count; ++index) {
      total_distance[index] = prefix_sum;
      prefix_sum += (int)seats[index];
    }
 
    // Start from second seat onwards,
    // this is the curr seat 'i'
    for (int i = 1; i < seats.Count; ++i) {
      for (int j = 0; j < i; ++j) {
        if (total_distance[i] - total_distance[j]
            >= dist)
          dp[i] += dp[j];
      }
    }
 
    // Account for no seat occupied
    return sum(dp) + 1;
  }
 
  // Driver code
  public static void Main()
  {
    ArrayList list = new ArrayList();
 
    list.Add(5);
    list.Add(2);
    list.Add(4);
    list.Add(1);
    list.Add(2);
 
    int ans = get_possible_seatings(list);
    Console.Write(ans);
  }
}
 
// This code is contributed by Samim Hossain Mondal.


Javascript




<script>
        // JavaScript code for the above approach
 
        // sum function
        function sum(v) {
            let res = 0;
            for (let dt of v)
                res += dt;
            return res;
        }
 
        // Function to count all valid arrangements
        function get_possible_seatings(seats) {
            let dist = 6;
 
            // Account for the last seat
            seats.push(0);
 
            // Each seat can be occupied individually
            let dp = new Array(seats.length).fill(1);
 
            // Keep track of total distance
            // from first seat
            let total_distance = new Array(seats.length).fill(0)
            let prefix_sum = seats[0];
            for (let index = 1; index < seats.length; ++index) {
                total_distance[index] = prefix_sum;
                prefix_sum += seats[index];
            }
 
            // Start from second seat onwards,
            // this is the curr seat 'i'
            for (let i = 1; i < seats.length; ++i) {
                for (let j = 0; j < i; ++j) {
                    if (total_distance[i] - total_distance[j]
                        >= dist)
                        dp[i] += dp[j];
                }
            }
 
            // Account for no seat occupied
            return sum(dp) + 1;
        }
 
        // Driver code
        let list = [5, 2, 4, 1, 2];
        let ans = get_possible_seatings(list);
        document.write(ans);
 
     // This code is contributed by Potta Lokesh
    </script>


Output

16

 
 

Output

16

 

Time Complexity: O(N2)
Auxiliary Space: O(N)

Another Approach: Use 2-pointer sliding window technique. 
 

  1. Each seat can be occupied individually so initialize an array of n+1 seats by 1
  2. We keep a track of the total right_prefix_sum and left_prefix_sum
  3. While right_prefix_sum – left_prefix_sum >= preferred_distance, keep shrinking left window and keep increasing the left_prefix_sum. Also, keep track of the count of all the previous number of arrangements
  4. Once we can’t shrink the window any further:
      dp[right + 1] = dp[right + 1] + count of previous number of arrangements
    Why right + 1 ?
      Since it’s the distance b/w seats, at each index, we are actually looking at index+1 seat number
     

Note:

We keep expanding the window(move right) till we are at the desired distance. Then keep shrinking from left and keep the total count of previous seats

This previous_arrangements count helps us in not restarting from 0 as we know the total count till any given index and if right – left prefix_sum >= preferred_distance, then all seats further to left can always be occupied

Below is the implementation of the above approach:

Python3




def get_possible_seatings(distances, pref_dist):
  left = right = 0
  previous_arrangements = 0
  right_prefix_sum = 0
  left_prefix_sum = 0
 
  dp = [1] * (len(distances) + 1)
 
  while right < len(distances):
      right_prefix_sum += distances[right]
 
      while right_prefix_sum - left_prefix_sum >= pref_dist:
          left_prefix_sum += distances[left]
          previous_arrangements += dp[left]
          left += 1
      dp[right+1] += previous_arrangements
      right += 1
 
  return sum(dp) + 1
 
# Driver code
if __name__ == "__main__":
    seats = [5, 2, 4, 1, 2]
    ans = get_possible_seatings(seats, 6)
    print(ans)


Javascript




// JS implementation for the above approach
function getPossibleSeatings(distances, prefDist) {
  let left = 0;
  let right = 0;
  let previousArrangements = 0;
  let rightPrefixSum = 0;
  let leftPrefixSum = 0;
 
  let dp = Array(distances.length + 1).fill(1);
 
  while (right < distances.length) {
      rightPrefixSum += distances[right];
 
      while (rightPrefixSum - leftPrefixSum >= prefDist) {
          leftPrefixSum += distances[left];
          previousArrangements += dp[left];
          left += 1;
      }
      dp[right+1] += previousArrangements;
      right += 1;
  }
 
  return dp.reduce((a, b) => a + b) + 1;
}
 
 
    const seats = [5, 2, 4, 1, 2];
    const ans = getPossibleSeatings(seats, 6);
    console.log(ans);
 
// This code is contributed by ik_9


C#




using System;
namespace SeatArrangement
{
  class Program
  {
    static int GetPossibleSeatings(int[] distances, int prefDist)
    {
      int left = 0;
      int right = 0;
      int previousArrangements = 0;
      int rightPrefixSum = 0;
      int leftPrefixSum = 0;
 
      int[] dp = new int[distances.Length + 1];
      for (int i = 0; i < dp.Length; i++)
      {
        dp[i] = 1;
      }
 
      while (right < distances.Length)
      {
        rightPrefixSum += distances[right];
 
        while (rightPrefixSum - leftPrefixSum >= prefDist)
        {
          leftPrefixSum += distances[left];
          previousArrangements += dp[left];
          left++;
        }
        dp[right + 1] += previousArrangements;
        right++;
      }
 
      int ans = 0;
      for (int i = 0; i < dp.Length; i++)
      {
        ans += dp[i];
      }
 
      return ans + 1;
    }
    //Driver code
 
    static void Main(string[] args)
    {
      int[] seats = new int[] { 5, 2, 4, 1, 2 };
      int ans = GetPossibleSeatings(seats, 6);
      Console.WriteLine(ans);
    }
  }
}


Java




/*package whatever //do not write package name here */
import java.util.*;
import java.io.*;
 
class GFG {
   public static int getPossibleSeatings(int[] distances, int prefDist) {
    int left = 0;
    int right = 0;
    int previousArrangements = 0;
    int rightPrefixSum = 0;
    int leftPrefixSum = 0;
 
    int[] dp = new int[distances.length + 1];
    // filling the arrays with one
    Arrays.fill(dp, 1);
    // continue when we have less than distance.length
    while (right < distances.length) {
        rightPrefixSum += distances[right];
 
        while (rightPrefixSum - leftPrefixSum >= prefDist) {
            leftPrefixSum += distances[left];
            previousArrangements += dp[left];
            left += 1;
        }
        dp[right+1] += previousArrangements;
        right += 1;
    }
 
    int totalArrangements = 0;
    for (int i = 0; i < dp.length; i++) {
        totalArrangements += dp[i];
    }
    return totalArrangements + 1;
}
// Driver code
public static void main(String[] args) {
  // Number of seats
    int[] seats = {5, 2, 4, 1, 2};
  // Function call
    int ans = getPossibleSeatings(seats, 6);
  // Printing the  answer
    System.out.println(ans);
}
}


C++14




// C++ program to implement the approach
 
#include <bits/stdc++.h>
#include <vector>
 
using namespace std;
 
// Function to count all valid arrangements
int get_possible_seatings(vector<int>& seats, int pref_dist)
{
    int left = 0;
    int right = 0;
    int previous_arrangements = 0;
    int right_prefix_sum = 0;
    int left_prefix_sum = 0;
    vector<int> dp(seats.size() + 1, 1);
 
    while (right < seats.size()) {
        right_prefix_sum += seats[right];
 
        while (right_prefix_sum - left_prefix_sum
               >= pref_dist) {
            left_prefix_sum += seats[left];
            previous_arrangements += dp[left];
            left += 1;
        }
        dp[right + 1] += previous_arrangements;
        right += 1;
    }
 
    int total_arrangements = 0;
    for (int i = 0; i < dp.size(); i++) {
        total_arrangements += dp[i];
    }
    return total_arrangements + 1;
}
 
// Driver code
int main()
{
    vector<int> seats = { 5, 2, 4, 1, 2 };
    int ans = get_possible_seatings(seats, 6);
    cout << ans << endl;
    return 0;
}


Output

16

Time Complexity: O(N)
Auxiliary Space: O(N)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads