拉胡尔和安吉特是皇家餐厅仅有的两名服务员。今天,餐厅接到N个订单。不同服务员处理的小费金额可能会有所不同,如果Rahul点第i个订单,他会得到Ai卢比的小费,如果Ankit接受这个订单,他就会得到Bi卢比的小费。
为了最大化总小费价值,他们决定在他们之间分配订单。一份订单将只由一个人处理。此外,由于时间限制,Rahul 不能接受多于X 个订单,而 Ankit 不能接受多于Y 个订单。保证X + Y大于或等于N ,这意味着所有订单都可以由 Rahul 或 Ankit 处理。在处理完所有订单后,找出最大可能的总小费金额。
例子:
Input: A[] = {1, 2, 3, 4, 5}, B[] = {5, 4, 3, 2, 1}, X = 3, Y = 3
Output: 21
1st, 2nd and 3rd orders are taken by waiter Y.
4th and 5th orders are taken by waiter X.
Input: A[] = {2, 2, 2}, B[] = {3, 3, 3}, X = 3, Y = 3
Output: 9
递归解决方案:我们可以通过递归的方式来计算以这种方式接受的最大金额订单
总小费将是最大的。该解决方案将包含 4 种情况:
- i == n:达到此值时,表示已接受所有订单。所以返回0并返回。
- X ≤ 0:当服务员X不能接受更多订单时。
- Y ≤ 0:当服务员Y不能接受更多订单时。
- max(Orders(X), Orders(Y)):当X和Y都接受订单时,我们需要返回小费的最大值。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
int n;
// Recursive function to calculate sum of
// maximum tip order taken by X and Y
int solve(int i, int X, int Y,
int a[], int b[], int n)
{
// When all orders have been taken
if (i == n)
return 0;
// When X cannot take more orders
if (X <= 0)
return b[i] + solve(i + 1, X,
Y - 1, a, b, n);
// When Y cannot take more orders
if (Y <= 0)
return a[i] + solve(i + 1, X - 1,
Y, a, b, n);
// When both can take order
// calculate maximum out of two
else
return max(a[i] + solve(i + 1, X - 1,
Y, a, b, n),
b[i] + solve(i + 1, X,
Y - 1, a, b, n));
}
// Driver code
int main()
{
int a[] = { 1, 2, 3, 4, 5 };
int b[] = { 5, 4, 3, 2, 1 };
int n = sizeof(a) / sizeof(a[0]);
int x = 3, y = 3;
cout << solve(0, x, y, a, b, n);
return 0;
}
Java
// Java implementation for the above approach
import java.io.*;
class GFG
{
static int n;
// Recursive function to calculate sum of
// maximum tip order taken by X and Y
static int solve(int i, int X, int Y, int a[], int b[],
int n)
{
// When all orders have been taken
if (i == n)
return 0;
// When X cannot take more orders
if (X <= 0)
return b[i] + solve(i + 1, X, Y - 1, a, b, n);
// When Y cannot take more orders
if (Y <= 0)
return a[i] + solve(i + 1, X - 1, Y, a, b, n);
// When both can take order
// calculate maximum out of two
else
return Math.max(
a[i] + solve(i + 1, X - 1, Y, a, b, n),
b[i] + solve(i + 1, X, Y - 1, a, b, n));
}
// Driver code
public static void main(String[] args)
{
int a[] = { 1, 2, 3, 4, 5 };
int b[] = { 5, 4, 3, 2, 1 };
int n = a.length;
int x = 3, y = 3;
System.out.println(solve(0, x, y, a, b, n));
}
}
// This code is contributed by Potta Lokesh
Python3
# Python3 program for the above approach
# Recursive function to calculate sum of
# maximum tip order taken by X and Y
def solve(i, X, Y,
a, b, n) :
# When all orders have been taken
if (i == n):
return 0
# When X cannot take more orders
if (X <= 0):
return (b[i] + solve(i + 1, X,
Y - 1, a, b, n))
# When Y cannot take more orders
if (Y <= 0):
return (a[i] + solve(i + 1, X - 1,
Y, a, b, n))
# When both can take order
# calculate maximum out of two
else:
return max(a[i] + solve(i + 1, X - 1,
Y, a, b, n),
b[i] + solve(i + 1, X,
Y - 1, a, b, n))
# Driver code
a = [ 1, 2, 3, 4, 5 ]
b = [ 5, 4, 3, 2, 1 ]
n = len(a)
x = 3
y = 3
print(solve(0, x, y, a, b, n))
# This code is contributed by splevel62.
C#
// C# program for the above approach
using System;
class GFG{
static int n;
// Recursive function to calculate sum of
// maximum tip order taken by X and Y
static int solve(int i, int X, int Y,
int[] a, int[] b, int n)
{
// When all orders have been taken
if (i == n)
return 0;
// When X cannot take more orders
if (X <= 0)
return b[i] + solve(i + 1, X, Y - 1,
a, b, n);
// When Y cannot take more orders
if (Y <= 0)
return a[i] + solve(i + 1, X - 1, Y,
a, b, n);
// When both can take order
// calculate maximum out of two
else
return Math.Max(
a[i] + solve(i + 1, X - 1, Y, a, b, n),
b[i] + solve(i + 1, X, Y - 1, a, b, n));
}
// Driver Code
public static void Main(String[] args)
{
int[] a = { 1, 2, 3, 4, 5 };
int[] b = { 5, 4, 3, 2, 1 };
// int n = a.Length;
int x = 3, y = 3;
Console.Write(solve(0, x, y, a, b, n));
}
}
// This code is contributed by sanjoy_62
Javascript
C++
// C++ implementation of the approach
#include
using namespace std;
// Global Variables
int N, X, Y;
vector A_right_sum, B_right_sum;
vector > >
mem;
vector > >
vis;
// Function to check if visited before
bool get_vis_val(int i, int x, int y)
{
if (i == N)
return true;
return vis[i][x][y];
}
// Function to return the tip value
int get_mem_val(int i, int x, int y)
{
if (i == N)
return 0;
return mem[i][x][y];
}
// Function to calculate the maximum tip possible
void find_ans(int i, int x, int y,
vector A, vector B)
{
// If already visited
if (get_vis_val(i, x, y))
return;
vis[i][x][y] = true;
// If X cannot take more orders
if (x == 0) {
mem[i][x][y] = B_right_sum[i];
}
// If Y cannot take more orders
else if (y == 0) {
mem[i][x][y] = A_right_sum[i];
}
// If both can take orders then
// calculate the maximum of two
else {
find_ans(i + 1, x - 1, y, A, B);
find_ans(i + 1, x, y - 1, A, B);
mem[i][x][y]
= max(get_mem_val(i + 1, x - 1, y)
+ A[i],
get_mem_val(i + 1, x, y - 1)
+ B[i]);
}
}
// Driver code
int main()
{
int a[] = { 1, 2, 3, 4, 5 };
int b[] = { 5, 4, 3, 2, 1 };
N = sizeof(a) / sizeof(a[0]);
X = 3;
Y = 3;
// Vector containing the tips of waiter X
vector A(a, a + N);
// Vector containing the tips of waiter Y
vector B(b, b + N);
// Memory allocation and clearing
// of previous caches
mem.clear();
mem.resize(N + 1);
vis.clear();
vis.resize(N + 1);
A_right_sum.resize(N);
B_right_sum.resize(N);
A_right_sum[N - 1] = A[N - 1];
B_right_sum[N - 1] = B[N - 1];
// Precalculation of sums
// of tip at each ith order
for (int i = N - 2; i >= 0; i--) {
A_right_sum[i]
= A_right_sum[i + 1] + A[i];
B_right_sum[i]
= B_right_sum[i + 1] + B[i];
}
// Bottom up dp based solution
find_ans(0, X, Y, A, B);
// Final ans stored in mem[0][X][Y]
cout << get_mem_val(0, X, Y) << endl;
return 0;
}
21
时间复杂度: O(2 n )
基于 DP 的方法:先前方法的最佳子结构包含重复,可以通过将先前计算的提示存储在数组中来避免重复。这会将时间复杂度降低到 O(n)。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
// Global Variables
int N, X, Y;
vector A_right_sum, B_right_sum;
vector > >
mem;
vector > >
vis;
// Function to check if visited before
bool get_vis_val(int i, int x, int y)
{
if (i == N)
return true;
return vis[i][x][y];
}
// Function to return the tip value
int get_mem_val(int i, int x, int y)
{
if (i == N)
return 0;
return mem[i][x][y];
}
// Function to calculate the maximum tip possible
void find_ans(int i, int x, int y,
vector A, vector B)
{
// If already visited
if (get_vis_val(i, x, y))
return;
vis[i][x][y] = true;
// If X cannot take more orders
if (x == 0) {
mem[i][x][y] = B_right_sum[i];
}
// If Y cannot take more orders
else if (y == 0) {
mem[i][x][y] = A_right_sum[i];
}
// If both can take orders then
// calculate the maximum of two
else {
find_ans(i + 1, x - 1, y, A, B);
find_ans(i + 1, x, y - 1, A, B);
mem[i][x][y]
= max(get_mem_val(i + 1, x - 1, y)
+ A[i],
get_mem_val(i + 1, x, y - 1)
+ B[i]);
}
}
// Driver code
int main()
{
int a[] = { 1, 2, 3, 4, 5 };
int b[] = { 5, 4, 3, 2, 1 };
N = sizeof(a) / sizeof(a[0]);
X = 3;
Y = 3;
// Vector containing the tips of waiter X
vector A(a, a + N);
// Vector containing the tips of waiter Y
vector B(b, b + N);
// Memory allocation and clearing
// of previous caches
mem.clear();
mem.resize(N + 1);
vis.clear();
vis.resize(N + 1);
A_right_sum.resize(N);
B_right_sum.resize(N);
A_right_sum[N - 1] = A[N - 1];
B_right_sum[N - 1] = B[N - 1];
// Precalculation of sums
// of tip at each ith order
for (int i = N - 2; i >= 0; i--) {
A_right_sum[i]
= A_right_sum[i + 1] + A[i];
B_right_sum[i]
= B_right_sum[i + 1] + B[i];
}
// Bottom up dp based solution
find_ans(0, X, Y, A, B);
// Final ans stored in mem[0][X][Y]
cout << get_mem_val(0, X, Y) << endl;
return 0;
}
21
时间复杂度: O(N)
空间复杂度: O(N 2 )
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。