📜  宝藏与城市

📅  最后修改于: 2021-04-30 02:34:18             🧑  作者: Mango

给定n个城市:x1,x2,……xn:每个城市都与T [i](宝藏)和C [i](颜色)相关。您可以选择参观或跳过城市。仅允许向前移动。访问城市时,您会收到以下金额:

  1. 如果访问城市的颜色与先前访问城市的颜色相同,则为A * T [i]
  2. B * T [i]如果这是第一个访问的城市,或者访问的城市的颜色与先前访问的城市的颜色不同。T[i],A和B的值可以为负,而C [i ]的范围是1到n。

我们必须计算可能的最大利润。

例子:

Input :  A = -5, B = 7
Treasure = {4, 8, 2, 9}
color = {2, 2, 3, 2}
Output : 133
Visit city 2, 3 and 4. Profit = 8*7+2*7+9*7 = 133

Input : A = 5, B = -7 
Treasure = {4, 8, 2, 9}
color = {2, 2, 3, 2}
Output: 57
Visit city 1, 2, 4. Profit = (-7)*4+8*5+9*5 = 57

资料来源:Oracle Interview Experience Set 61。

这是标准0/1背包问题的变体。想法是访问一个城市或跳过它,然后返回两种情况的最大值。

以下是上述问题的解决方案。

C++
#include 
using namespace std;
  
// k is current index and col is previous color.
int MaxProfit(int treasure[], int color[], int n,
              int k, int col, int A, int B)
{
    int sum = 0;
  
    if (k == n) // base case
        return 0;
  
    // we have two options
    // either visit current city or skip that
  
    // check if color of this city is equal
    // to prev visited city
    if (col == color[k])
        sum += max(A * treasure[k] + 
                MaxProfit(treasure, color, n, 
                       k + 1, color[k], A, B),
                MaxProfit(treasure, color, n, 
                          k + 1, col, A, B));
    else
        sum += max(B * treasure[k] +                                          
                MaxProfit(treasure, color, n,
                       k + 1, color[k], A, B),
               MaxProfit(treasure, color, n, 
                          k + 1, col, A, B));
  
    // return max of both options
    return sum;
}
  
int main()
{
  
    int A = -5, B = 7;
    int treasure[] = { 4, 8, 2, 9 };
    int color[] = { 2, 2, 6, 2 };
    int n = sizeof(color) / sizeof(color[0]);
  
    // Initially begin with color 0
    cout << MaxProfit(treasure, color, n, 0, 0, A, B);
    return 0;
}


Java
class GFG{ 
  
// k is current index and col is previous color. 
static int MaxProfit(int treasure[], int color[], int n, 
            int k, int col, int A, int B) 
{ 
    int sum = 0; 
  
    if (k == n) // base case 
        return 0; 
  
    // we have two options 
    // either visit current city or skip that 
  
    // check if color of this city is equal 
    // to prev visited city 
    if (col == color[k]) 
        sum += Math.max(A * treasure[k] + 
                MaxProfit(treasure, color, n, 
                    k + 1, color[k], A, B), 
                MaxProfit(treasure, color, n, 
                        k + 1, col, A, B)); 
    else
        sum += Math.max(B * treasure[k] +                                         
                MaxProfit(treasure, color, n, 
                    k + 1, color[k], A, B), 
            MaxProfit(treasure, color, n, 
                        k + 1, col, A, B)); 
  
    // return max of both options 
    return sum; 
} 
  
public static void main(String[] args) 
{ 
  
    int A = -5, B = 7; 
    int treasure[] = { 4, 8, 2, 9 }; 
    int color[] = { 2, 2, 6, 2 }; 
    int n = color.length; 
  
    // Initially begin with color 0 
    System.out.print(MaxProfit(treasure, color, n, 0, 0, A, B)); 
}
} 
  
// This code is contributed by PrinciRaj1992


Python3
# k is current index and col
# is previous color. 
def MaxProfit(treasure, color, n, 
                    k, col, A, B):
    sum = 0
    if k == n:
        return 0
  
    # we have two options either
    # visit current city or skip that 
  
    # check if color of this city 
    # is equal to prev visited city 
    if col== color[k]:
        sum += max(A * treasure[k] +
                MaxProfit(treasure, color, n, 
                       k + 1, color[k], A, B), 
                MaxProfit(treasure, color, n, 
                            k + 1, col, A, B))
    else:
        sum += max(B * treasure[k] +                                        
               MaxProfit(treasure, color, n, 
                        k + 1, color[k], A, B), 
               MaxProfit(treasure, color, n, 
                           k + 1, col, A, B))
  
    # return max of both options
    return sum
  
# Driver Code
A = -5
B= 7
treasure = [4, 8, 2, 9]
color = [2, 2, 6, 2]
n = len(color)
  
# Initially begin with color 0
print( MaxProfit(treasure, color,
                 n, 0, 0, A, B))
  
# This code is contributed 
# by Shrikant13


C#
using System;
  
class GFG
{ 
  
// k is current index and col is previous color. 
static int MaxProfit(int []treasure, int []color, int n, 
            int k, int col, int A, int B) 
{ 
    int sum = 0; 
  
    if (k == n) // base case 
        return 0; 
  
    // we have two options 
    // either visit current city or skip that 
  
    // check if color of this city is equal 
    // to prev visited city 
    if (col == color[k]) 
        sum += Math.Max(A * treasure[k] + 
                MaxProfit(treasure, color, n, 
                    k + 1, color[k], A, B), 
                MaxProfit(treasure, color, n, 
                        k + 1, col, A, B)); 
    else
        sum += Math.Max(B * treasure[k] +                                         
                MaxProfit(treasure, color, n, 
                    k + 1, color[k], A, B), 
            MaxProfit(treasure, color, n, 
                        k + 1, col, A, B)); 
  
    // return max of both options 
    return sum; 
} 
  
// Driver code
public static void Main(String[] args) 
{ 
  
    int A = -5, B = 7; 
    int []treasure = { 4, 8, 2, 9 }; 
    int []color = { 2, 2, 6, 2 }; 
    int n = color.Length; 
  
    // Initially begin with color 0 
    Console.Write(MaxProfit(treasure, color, n, 0, 0, A, B)); 
}
} 
  
// This code is contributed by PrinciRaj1992


C++
// A memoization based program to find maximum
// treasure that can be collected.
#include 
using namespace std;
  
const int MAX = 1001;
  
int dp[MAX][MAX];
  
// k is current index and col is previous color.
int MaxProfit(int treasure[], int color[], int n,
              int k, int col, int A, int B)
{
    if (k == n) // base case
        return dp[k][col] = 0;
  
    if (dp[k][col] != -1)
        return dp[k][col];
  
    int sum = 0;
  
    // we have two options
    // either visit current city or skip that
  
    if (col == color[k]) // check if color of this city is equal to prev visited city
        sum += max(A * treasure[k] + 
               MaxProfit(treasure, color, n, k + 1, 
                                     color[k], A, B),  
               MaxProfit(treasure, color, n, k + 1, 
                                        col, A, B));
    else
        sum += max(B * treasure[k] + 
                MaxProfit(treasure, color, n, k + 1, 
                                   color[k], A, B), 
                MaxProfit(treasure, color, n, k + 1, 
                                        col, A, B));
  
    // return max of both options
    return dp[k][col] = sum;
}
  
int main()
{
    int A = -5, B = 7;
    int treasure[] = { 4, 8, 2, 9 };
    int color[] = { 2, 2, 6, 2 };
    int n = sizeof(color) / sizeof(color[0]);
    memset(dp, -1, sizeof(dp));
    cout << MaxProfit(treasure, color, n, 0, 0, A, B);
    return 0;
}


Java
// A memoization based program to find maximum
// treasure that can be collected.
import java.util.*;
  
class GFG
{
  
static int MAX = 1001;
  
static int [][]dp = new int[MAX][MAX];
  
// k is current index and col is previous color.
static int MaxProfit(int treasure[], int color[], int n,
            int k, int col, int A, int B)
{
    if (k == n) // base case
        return dp[k][col] = 0;
  
    if (dp[k][col] != -1)
        return dp[k][col];
  
    int sum = 0;
  
    // we have two options
    // either visit current city or skip that
      
    // check if color of this city 
    // is equal to prev visited city
    if (col == color[k]) 
        sum += Math.max(A * treasure[k] + 
            MaxProfit(treasure, color, n, k + 1, 
                                    color[k], A, B), 
            MaxProfit(treasure, color, n, k + 1, 
                                        col, A, B));
    else
        sum += Math.max(B * treasure[k] + 
                MaxProfit(treasure, color, n, k + 1, 
                                color[k], A, B), 
                MaxProfit(treasure, color, n, k + 1, 
                                        col, A, B));
  
    // return max of both options
    return dp[k][col] = sum;
}
  
// Driver code
public static void main(String[] args)
{
    int A = -5, B = 7;
    int treasure[] = { 4, 8, 2, 9 };
    int color[] = { 2, 2, 6, 2 };
    int n = color.length;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < MAX; j++)
            dp[i][j] = -1;
    System.out.print(MaxProfit(treasure, color, n, 0, 0, A, B));
}
}
  
// This code is contributed by 29AjayKumar


Python3
# A memoization based program to find maximum
# treasure that can be collected.
MAX = 1001
  
dp = [[-1 for i in range(MAX)] for i in range(MAX)]
  
# k is current index and col is previous color.
def MaxProfit(treasure, color, n,k, col, A, B):
    if (k == n):
          
        # base case
        dp[k][col] = 0
        return dp[k][col]
    if (dp[k][col] != -1):
        return dp[k][col]
      
    summ = 0
      
    # we have two options
    # either visit current city or skip that
    if (col == color[k]):
          
        # check if color of this city is equal to prev visited city
        summ += max(A * treasure[k] + MaxProfit(treasure, 
                color, n, k + 1,color[k], A, B),
                MaxProfit(treasure, color, n, k + 1, col, A, B))
    else:
        summ += max(B * treasure[k] + MaxProfit(treasure,
                color, n, k + 1,color[k], A, B), 
                MaxProfit(treasure, color, n, k + 1, col, A, B))
    dp[k][col] = summ
      
    # return max of both options
    return dp[k][col]
  
# Driver code
A = -5
B = 7
treasure = [ 4, 8, 2, 9 ]
color = [ 2, 2, 6, 2 ]
n = len(color)
print(MaxProfit(treasure, color, n, 0, 0, A, B))
  
# This code is contributed by shubhamsingh10


C#
// A memoization based program to find maximum
// treasure that can be collected.
using System;
  
class GFG
{
   
static int MAX = 1001;
   
static int [,]dp = new int[MAX, MAX];
   
// k is current index and col is previous color.
static int MaxProfit(int []treasure, int []color, int n,
            int k, int col, int A, int B)
{
    if (k == n) // base case
        return dp[k, col] = 0;
   
    if (dp[k, col] != -1)
        return dp[k, col];
   
    int sum = 0;
   
    // we have two options
    // either visit current city or skip that
       
    // check if color of this city 
    // is equal to prev visited city
    if (col == color[k]) 
        sum += Math.Max(A * treasure[k] + 
            MaxProfit(treasure, color, n, k + 1, 
                                    color[k], A, B), 
            MaxProfit(treasure, color, n, k + 1, 
                                        col, A, B));
    else
        sum += Math.Max(B * treasure[k] + 
                MaxProfit(treasure, color, n, k + 1, 
                                color[k], A, B), 
                MaxProfit(treasure, color, n, k + 1, 
                                        col, A, B));
   
    // return max of both options
    return dp[k, col] = sum;
}
   
// Driver code
public static void Main(String[] args)
{
    int A = -5, B = 7;
    int []treasure = { 4, 8, 2, 9 };
    int []color = { 2, 2, 6, 2 };
    int n = color.Length;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < MAX; j++)
            dp[i, j] = -1;
    Console.Write(MaxProfit(treasure, color, n, 0, 0, A, B));
}
}
  
// This code is contributed by PrinciRaj1992


输出:
133

由于再次评估了优势,因此此问题具有“重叠子问题”属性。
以下是基于动态编程的实现。

C++

// A memoization based program to find maximum
// treasure that can be collected.
#include 
using namespace std;
  
const int MAX = 1001;
  
int dp[MAX][MAX];
  
// k is current index and col is previous color.
int MaxProfit(int treasure[], int color[], int n,
              int k, int col, int A, int B)
{
    if (k == n) // base case
        return dp[k][col] = 0;
  
    if (dp[k][col] != -1)
        return dp[k][col];
  
    int sum = 0;
  
    // we have two options
    // either visit current city or skip that
  
    if (col == color[k]) // check if color of this city is equal to prev visited city
        sum += max(A * treasure[k] + 
               MaxProfit(treasure, color, n, k + 1, 
                                     color[k], A, B),  
               MaxProfit(treasure, color, n, k + 1, 
                                        col, A, B));
    else
        sum += max(B * treasure[k] + 
                MaxProfit(treasure, color, n, k + 1, 
                                   color[k], A, B), 
                MaxProfit(treasure, color, n, k + 1, 
                                        col, A, B));
  
    // return max of both options
    return dp[k][col] = sum;
}
  
int main()
{
    int A = -5, B = 7;
    int treasure[] = { 4, 8, 2, 9 };
    int color[] = { 2, 2, 6, 2 };
    int n = sizeof(color) / sizeof(color[0]);
    memset(dp, -1, sizeof(dp));
    cout << MaxProfit(treasure, color, n, 0, 0, A, B);
    return 0;
}

Java

// A memoization based program to find maximum
// treasure that can be collected.
import java.util.*;
  
class GFG
{
  
static int MAX = 1001;
  
static int [][]dp = new int[MAX][MAX];
  
// k is current index and col is previous color.
static int MaxProfit(int treasure[], int color[], int n,
            int k, int col, int A, int B)
{
    if (k == n) // base case
        return dp[k][col] = 0;
  
    if (dp[k][col] != -1)
        return dp[k][col];
  
    int sum = 0;
  
    // we have two options
    // either visit current city or skip that
      
    // check if color of this city 
    // is equal to prev visited city
    if (col == color[k]) 
        sum += Math.max(A * treasure[k] + 
            MaxProfit(treasure, color, n, k + 1, 
                                    color[k], A, B), 
            MaxProfit(treasure, color, n, k + 1, 
                                        col, A, B));
    else
        sum += Math.max(B * treasure[k] + 
                MaxProfit(treasure, color, n, k + 1, 
                                color[k], A, B), 
                MaxProfit(treasure, color, n, k + 1, 
                                        col, A, B));
  
    // return max of both options
    return dp[k][col] = sum;
}
  
// Driver code
public static void main(String[] args)
{
    int A = -5, B = 7;
    int treasure[] = { 4, 8, 2, 9 };
    int color[] = { 2, 2, 6, 2 };
    int n = color.length;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < MAX; j++)
            dp[i][j] = -1;
    System.out.print(MaxProfit(treasure, color, n, 0, 0, A, B));
}
}
  
// This code is contributed by 29AjayKumar

Python3

# A memoization based program to find maximum
# treasure that can be collected.
MAX = 1001
  
dp = [[-1 for i in range(MAX)] for i in range(MAX)]
  
# k is current index and col is previous color.
def MaxProfit(treasure, color, n,k, col, A, B):
    if (k == n):
          
        # base case
        dp[k][col] = 0
        return dp[k][col]
    if (dp[k][col] != -1):
        return dp[k][col]
      
    summ = 0
      
    # we have two options
    # either visit current city or skip that
    if (col == color[k]):
          
        # check if color of this city is equal to prev visited city
        summ += max(A * treasure[k] + MaxProfit(treasure, 
                color, n, k + 1,color[k], A, B),
                MaxProfit(treasure, color, n, k + 1, col, A, B))
    else:
        summ += max(B * treasure[k] + MaxProfit(treasure,
                color, n, k + 1,color[k], A, B), 
                MaxProfit(treasure, color, n, k + 1, col, A, B))
    dp[k][col] = summ
      
    # return max of both options
    return dp[k][col]
  
# Driver code
A = -5
B = 7
treasure = [ 4, 8, 2, 9 ]
color = [ 2, 2, 6, 2 ]
n = len(color)
print(MaxProfit(treasure, color, n, 0, 0, A, B))
  
# This code is contributed by shubhamsingh10

C#

// A memoization based program to find maximum
// treasure that can be collected.
using System;
  
class GFG
{
   
static int MAX = 1001;
   
static int [,]dp = new int[MAX, MAX];
   
// k is current index and col is previous color.
static int MaxProfit(int []treasure, int []color, int n,
            int k, int col, int A, int B)
{
    if (k == n) // base case
        return dp[k, col] = 0;
   
    if (dp[k, col] != -1)
        return dp[k, col];
   
    int sum = 0;
   
    // we have two options
    // either visit current city or skip that
       
    // check if color of this city 
    // is equal to prev visited city
    if (col == color[k]) 
        sum += Math.Max(A * treasure[k] + 
            MaxProfit(treasure, color, n, k + 1, 
                                    color[k], A, B), 
            MaxProfit(treasure, color, n, k + 1, 
                                        col, A, B));
    else
        sum += Math.Max(B * treasure[k] + 
                MaxProfit(treasure, color, n, k + 1, 
                                color[k], A, B), 
                MaxProfit(treasure, color, n, k + 1, 
                                        col, A, B));
   
    // return max of both options
    return dp[k, col] = sum;
}
   
// Driver code
public static void Main(String[] args)
{
    int A = -5, B = 7;
    int []treasure = { 4, 8, 2, 9 };
    int []color = { 2, 2, 6, 2 };
    int n = color.Length;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < MAX; j++)
            dp[i, j] = -1;
    Console.Write(MaxProfit(treasure, color, n, 0, 0, A, B));
}
}
  
// This code is contributed by PrinciRaj1992
输出:
133