📜  计算在给定约束下修建街道的方法

📅  最后修改于: 2021-05-07 07:59:23             🧑  作者: Mango

有一条长度为n的街道,而且我们知道它有两条边。因此,总共有2 * n个斑点可用。在这些地点中的每个地点,都可以按照以下两个限制来建造房屋或办公室:

1.街道同一侧的两个办公室不能相邻。
2.街道两边的两个办公室都不能彼此完全相对,即它们不能相互忽视。
建造房屋没有任何限制,每个地点都必须有房屋或办公室。
在给定的街道长度n的基础上,找到建立街道的总数。

例子:

Input : 2
Output : 7
Please see below diagram for explanation.

Input : 3
Output : 17

下图描绘了在N = 2的情况下建造街道的7种可能方法

Ways for building street with length 1
with 2 houses: (H H) = {1}
with 1 office and 1 house: (O H) (H O) = {2}
(O O) is not allowed according to the problem statement.
Total = 1  + 2 = 3
For length = 2,
with 2 houses: (H H) can be added to all
the cases of length 1:

(H H)    (H H)    (H H)
(H H)    (O H)    (H O) = {3}

with 1 office and 1 house:
(O H) and (H O) can both be added to all 
the cases of length 1 with last row (H H)

(O H)    (H O)
(H H)    (H H) = {2}

when last row of a case of length 1 
contains 1 office, it can only be 
extended in one way to build an office
in row 2. 
(H O)    (O H)    
(O H)    (H O) = {2}

(O H)    (H O) (O O)    
(O H)    (H O) (O H) etc are not allowed.

Total = 3 + 2 + 2 = 7

由于可以通过找到较小的子问题的解决方案然后扩展相同的逻辑来解决该问题,因此可以使用动态编程来解决。我们以一个单位长度的步长移动。对于每一行,我们有两个选择:
在两个地方都盖房子
建一所房子和一间办公室
第一个可以不受任何限制地完成。在长度为i的两个位置上都有一种建造房屋的方法。因此,使用此选择的总方法=长度i – 1的总方法。
对于第二种选择,如果第(i-1)行在两个位置都有房屋,则我们有两种建立办公室的方式,即(HO)和(OH)
如果第(i-1)行在其两个位置中的一个位置设有办公室,则只有一种方法在第i行中建立办公室。如果上一行具有(OH),则当前行将具有(HO),对于上一行=( HO)curr row =(OH)。
根据上述逻辑,此选择的总数为= 2 *(choice1(i-1))+ choice2(i-1)
我们将为此构建一个2D dp。
dp [0] [i]表示第1行,而dp [1] [i]表示第i行。

下面是上述想法的实现:

C++
// C++ program to count ways to build street
// under given constraints
#include 
using namespace std;
 
// function to count ways of building
// a street of n rows
long countWays(int n)
{
    long dp[2][n + 1];
 
    // base case
    dp[0][1] = 1;
    dp[1][1] = 2;
 
    for (int i = 2; i <= n; i++) {
 
        // ways of building houses in both
        // the spots of ith row
        dp[0][i] = dp[0][i - 1] + dp[1][i - 1];
 
        // ways of building an office in one of
        // the two spots of ith row
        dp[1][i] = dp[0][i - 1] * 2 + dp[1][i - 1];
    }
 
    // total ways for n rows
    return dp[0][n] + dp[1][n];
}
 
// driver program for checking above function
int main()
{
 
    int n = 5;
    cout << "Total no of ways with n = " << n
         << " are: " << countWays(n) << endl;
}


Java
// Java program to count ways to build street
// under given constraints
public class GFG {
 
// function to count ways of building
// a street of n rows
    static long countWays(int n) {
        long dp[][] = new long[2][n + 1];
 
        // base case
        dp[0][1] = 1;
        dp[1][1] = 2;
 
        for (int i = 2; i <= n; i++) {
 
            // ways of building houses in both
            // the spots of ith row
            dp[0][i] = dp[0][i - 1] + dp[1][i - 1];
 
            // ways of building an office in one of
            // the two spots of ith row
            dp[1][i] = dp[0][i - 1] * 2 + dp[1][i - 1];
        }
 
        // total ways for n rows
        return dp[0][n] + dp[1][n];
    }
 
// driver program for checking above function
    public static void main(String[] args) {
 
        int n = 5;
        System.out.print("Total no of ways with n = " + n
                + " are: " + countWays(n));
    }
 
}
 
/*This code is contributed by PrinciRaj1992*/


Python3
# Python3 program to count ways to build
# street under given constraints
 
# function to count ways of building
# a street of n rows
def countWays(n) :
     
 
    dp = [[0] * (n + 1) for i in range(2)]
     
    # base case
    dp[0][1] = 1
    dp[1][1] = 2
     
    for i in range(2, n + 1) :
         
        # ways of building houses in both
        # the spots of ith row
        dp[0][i] = dp[0][i - 1] + dp[1][i - 1]
         
        # ways of building an office in one of
        # the two spots of ith row
        dp[1][i] = (dp[0][i - 1] * 2 +
                    dp[1][i - 1])
     
    # total ways for n rows
    return dp[0][n] + dp[1][n]
 
# Driver Code
if __name__ == "__main__" :
     
    n = 5
    print("Total no of ways with n =",
              n, "are:", countWays(n))
 
# This code is contributed by Ryuga


C#
// C# program to count ways to build street
// under given constraints
 
using System;
public class GFG{
 
 
// function to count ways of building
// a street of n rows
    static long countWays(int n) {
        long [,]dp = new long[2 , n + 1];
 
        // base case
        dp[0,1] = 1;
        dp[1,1] = 2;
 
        for (int i = 2; i <= n; i++) {
 
            // ways of building houses in both
            // the spots of ith row
            dp[0 , i] = dp[0 , i - 1] + dp[1 , i - 1];
 
            // ways of building an office in one of
            // the two spots of ith row
            dp[1 , i] = dp[0 , i - 1] * 2 + dp[1 , i - 1];
        }
 
        // total ways for n rows
        return dp[0 , n] + dp[1 , n];
    }
 
// driver program for checking above function
    public static void Main() {
 
        int n = 5;
        Console.Write("Total no of ways with n = " + n
                + " are: " + countWays(n));
    }
 
}
 
/*This code is contributed by PrinciRaj1992*/


PHP


C++
// C++ program of above approach
#include 
using namespace std;
 
// Program to count ways
int countways(long long n)
{
    long long A[n+1];
    A[0] = 1;
    A[1] = 3;
    A[2] = 7;
   
    // Iterate from 2 to n
    for(int i=2;i<=n;i++)
    {
        A[i] = 2*A[i-1]+A[i-2];
    }
    return A[n];
}
 
// Driver code
int main() {
    int n = 5;
   
    // Count Ways 
    cout << countways(5) << endl;
    return 0;
}


Python3
# Python3 program of above approach
 
# Program to count ways
def countways(n):
     
    A = [0 for i in range(n + 2)]
    A[0] = 1
    A[1] = 3
    A[2] = 7
 
    # Iterate from 2 to n
    for i in range(2, n + 1):
        A[i] = 2 * A[i - 1] + A[i - 2]
         
    return A[n]
 
# Driver code
n = 5
 
# Count Ways
print(countways(5))
 
# This code is contributed by Sanjit_Prasad


输出
Total no of ways with n = 5 are: 99

时间复杂度: O(N)
辅助空间: O(N)

另一种方法
假设您有A(n-1)和A(n-2),其中A(i)描绘了2 * i建筑物的方式,则:
A(n)=(在A(n-1)中具有(HH)的方式数)* 3 +(在A(n-1)中具有(OH)的方式数)* 2
这些情况是如何产生的?简而言之,您可以考虑将2个状态设为上述说明中所述的状态。
在A(n-1)中具有(HH)的路数=将HH固定在第(n-1)个位置,这等于n-2位置的路数(将n-1固定为HH)。
在A(n-1)中具有(OH)的路数=(在n-1中具有的路数)–(在A(n-1)位置中的HH的路数)。
所以A(n)= 3 * A(n-2)+ 2 *(A(n-1)-A(n-2))= 2 * A(n-1)+ A(n-2)

C++

// C++ program of above approach
#include 
using namespace std;
 
// Program to count ways
int countways(long long n)
{
    long long A[n+1];
    A[0] = 1;
    A[1] = 3;
    A[2] = 7;
   
    // Iterate from 2 to n
    for(int i=2;i<=n;i++)
    {
        A[i] = 2*A[i-1]+A[i-2];
    }
    return A[n];
}
 
// Driver code
int main() {
    int n = 5;
   
    // Count Ways 
    cout << countways(5) << endl;
    return 0;
}

Python3

# Python3 program of above approach
 
# Program to count ways
def countways(n):
     
    A = [0 for i in range(n + 2)]
    A[0] = 1
    A[1] = 3
    A[2] = 7
 
    # Iterate from 2 to n
    for i in range(2, n + 1):
        A[i] = 2 * A[i - 1] + A[i - 2]
         
    return A[n]
 
# Driver code
n = 5
 
# Count Ways
print(countways(5))
 
# This code is contributed by Sanjit_Prasad
输出
99

时间复杂度: O(N)
辅助空间: O(N)