如何计算n个售票窗口的m门票所赚取的最高金额,即票价与票房的票数相等?
火车站有n个售票窗口。带窗口的(j)门票可用。票价与当时该窗口中剩余的票数相等。出售前m票的火车站可以赚到的最高金额是多少?
例如,如果我们有3个售票窗口,有3个,3个,4个门票,我们想卖5张门票。然后:
n = 3, m = 5
A[3] = {3, 3, 4}
赚取的最高金额为4 + 3 + 3 + 3 + 2 = 15
我在网上看到了这个问题,我的解决方案是首先将所有门票号码推送到maxHeap并运行for循环m次。每次我们弹出maxHeap的最高值并将其添加到所赚取的总金额中,如果该值大于1,我们将(value - 1)推送到maxHeap。
但这在某种程度上耗费时间消耗更好的解决方案?
答案 0 :(得分:1)
要解决这个问题,我们需要做一个观察:
m
张票。让x
成为窗口中剩余的最大票数,因此一个窗口i
为总收入贡献的钱是
(a(i) + a(i) - 1 + ... + x + 1) = a(i)*(a(i) + 1)/2 - x*(x + 1)/2
要查找x
,我们可以使用二进制搜索
int start = 0;
int end = maximum number of ticket in one window;
while(start <= end)
int mid = (start + end)/2;
for(each window)
number of sell ticket += a(i) - mid;//if mid is larger than a(i), just add a zero
if(number of sell ticket >= m)
increase start;
else
decrease end;
因此,时间复杂度为O(n log m),n为窗口数,m为一个窗口中的最大票数。
答案 1 :(得分:0)
如果使用max heap,可以在O(m * logn)中完成。这是C ++代码 -
int main() {
int *inputArray;
int n;
int m;
cin >> n;
cin >> m;
inputArray = new int[n];
for (int i = 0; i < n; i++) {
cin >> inputArray[i];
}
cout << maximize(inputArray, n, m) << "\n";
return 0;
}
int maximize(int *inputArray, int n, int m){
vector<int> v(inputArray, inputArray + n);
int sum = 0;
// make max heap
make_heap(v.begin(), v.end());
for (m = 4; m != 0; m--) {
// get max value
int max = v.front();
// move max value to end and heapify
pop_heap(v.begin(), v.end());
// pop it out
v.pop_back();
sum = sum + max;
if (max - 1) {
// insert m-1 into vector
v.push_back(max - 1);
// heapify the new vector
push_heap(v.begin(), v.end());
}
}
return sum;
}
答案 2 :(得分:0)
package package1;
import java.util.Arrays;
import java.util.Scanner;
public class RailwayStation{
int numOfTickets, ticketsToSell;
int[] ticketsPerBooth;
public RailwayStation(int numOfTickets, int ticketsToSell, int[] ticketsPerBooth)
{
this.numOfTickets = numOfTickets;
this.ticketsToSell = ticketsToSell;
this.ticketsPerBooth = ticketsPerBooth;
}
public int findMaxRevenue()
{
int[] perBooth = this.ticketsPerBooth;
Arrays.sort(perBooth);
int i = perBooth.length-1;
int revenue = 0;
while(i>=0 && ticketsToSell!=0){
int diff = 0;
if(i==0){
diff = 1;
}else{
diff = perBooth[i] - perBooth[i-1];
}
while(diff!=0 && ticketsToSell!=0){
revenue = revenue + perBooth[i];
perBooth[i]--;
diff--;
ticketsToSell--;
}
if(ticketsToSell!=0 && i==0){
i = perBooth.length-1;
}else{
i--;
}
}
return revenue;
}
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int numOfBooths = sc.nextInt();
int ticketsToSell = sc.nextInt();
int perBooth[] = new int[numOfBooths];
for(int i = 0; i < numOfBooths; i++)
{
perBooth[i] = sc.nextInt();
}
RailwayStation rt = new RailwayStation(numOfBooths, ticketsToSell, perBooth);
System.out.println("Max Revenue = " + rt.findMaxRevenue());
}
}
答案 3 :(得分:0)
“”“修改后的阶乘,直到该轮的索引限制”“
def modified_fact(限制,数字): sum_fact = 0 对于范围内的i(数字 - 限制+ 1,数字+ 1): sum_fact + = i return sum_fact
''” 我已经计算了我需要做多少回合才能减少。在最后一次迭代中,我需要什么索引 迭代。
'''
def maximum_earning_algorithm(n,windows): “”“
:param windows:
:param n:
:rtype: int
"""
money = 0
final_round_limit_index = n % len(windows)
rounds = n / (len(windows))
print final_round_limit_index, rounds
for i in range(len(windows)):
if i < final_round_limit_index:
money += modified_fact(rounds + 1, windows[i])
else:
money += modified_fact(rounds, windows[i])
return money
如果名称 =='主要': 窗口= [5,4,3] print maximum_earning_algorithm(3,window)
答案 4 :(得分:0)
方法1)
作为@ n.m.指出MaxHeap解决方案的小优化:
您无需逐个删除票证。如果您有一个顶部窗口,您需要知道它有多少票,以及下一张票有多少票。然后,您可以删除差异并在一次操作中计算总价。 稍作修改,如果您有多个具有相同最大票数的窗口,则可以执行相同的操作。
方法2)使用排序数组:
将窗口加载到数组中。对数组进行排序。向后遍历数组并执行:存储该数字(当前),将其添加到聚合器,转到下一个值。如果它是相同的(当前),则将其添加到聚合器,从中减去1,继续。如果不同,请返回到数组的末尾并重新开始。做N次(内部循环,而不是外部循环)。
方法3)使用计数数组(线性时间复杂度):
创建索引为no的数组。门票和价值观没有。有许多门票的摊位。因此,{0-> 0,1-> 1,2-> 0,3-> 2}意味着1档有1张票,2档有3张票
从数组的最高索引(count -1)开始,将该索引添加到聚合器(A),使A = 3,然后将该索引(3)减少1比1,并增加索引低于(= 2)1到1 数组是{0,1,1,1},A = 3。重复。 A = 6,数组为{0,1,2,0}。最后一个索引为零,因此将指针移动到索引2 重复,所以A = 8,数组= {0,2,1,0}。重复。 A = 10,数组为{0,5,0,0} 你已经完成了t次(销售门票数量)停止。
以下是此方法的实施:
int[] stalls = new int[] { 3,1,3 }; // 2 stalls have 3 tickets each and 1 stall have 1 ticket
int t = 4;
Arrays.sort(stalls);
int tickets = stalls[stalls.length - 1];
int[] dp = new int[tickets + 1];
for (int i = 0; i < stalls.length; i++) {
dp[stalls[i]]++;
}
int total = 0;
int i = dp.length - 1;
while (t > 0) {
if (dp[i] > 0) {
total += i;
t--;
dp[i]--;
dp[i - 1]++;
} else {
i--;
}
}
System.out.println(total);