Code Jam 2008“价格错误” - 解释

时间:2016-08-03 20:32:24

标签: algorithm

我一直在浏览Code Jam档案。我真的在努力解决2008年Code Jam 价格错误的问题

问题陈述是 -

你正在玩一款游戏,你试图猜测各种产品的正确零售价格。在猜测列表中每个产品的价格后,您会看到按实际价格排序的相同产品列表,从最少到最贵。 (没有两种产品的成本相同。)根据这种排序,您只有一次机会改变一个或多个猜测。

您的程序应输出最小的产品集,这样,如果您更改这些产品的价格,您的猜测顺序将与产品列表的正确排序一致。返回集中的产品应按字母顺序列出。如果有多个最小集合,则输出首先按字典顺序出现的集合。

例如,假设这些是您的初步猜测:

代码= $ 20

jam = $ 15

foo = $ 40

bar = $ 30

google = $ 60

如果正确的订购是代码堵塞foo bar google,那么您需要更改两个价格以匹配正确的订购。你可以改变一个猜测来读取jam = $ 30和另一个猜测来读取bar = $ 50,这将匹配正确的顺序并产生输出设置条卡。但是,输出设置条形码按字典顺序排在条形图之前,您也可以通过更改这些项目的猜测来匹配正确的顺序。

实施例

Input
code jam foo bar google
20 15 40 30 60

Output
Case #1: bar code

我不是要求确切的解决方案,但是,我该如何处理问题

提前致谢。

2 个答案:

答案 0 :(得分:1)

好吧,经过一段时间的努力,我得到了小小的&大案件被接受。

在发布我丑陋丑陋的代码之前,这里有一些简短的解释:

首先,基于问题陈述和参数的限制,可以直观地认为问题的核心部分只是找到 最长增长子序列(LIS) < / strong>即可。它确实依靠你的经验来快速计算出来(事实上大多数情况都是在竞争性编程领域)。

这样想,如果我能找到价格形成LIS的物品组,那么剩下的物品是您需要更改的最小值。

但是你需要满足一个更多的要求,我认为这是这个问题最难的部分,就是当存在多个最小的集合时,你必须找到字典最小的一个。这与说找到带有词典编号最大名称的LIS (然后我们将它们扔掉,剩下的项目就是答案)

要做到这一点,有很多方法,但由于限制很小(N <= 64),你基本上可以使用任何算法(O(N^4)O(N^5)?来吧!)

我接受的方法是为LIS的传统O(N^2)动态编程添加一个愚蠢的转折:

DP(i)成为数字[0..i]中的LIS,必须选择数字

还使用set<string>数组来存储可以实现DP(i)的最佳项目名称,我们更新此数组以及进行动态编程以查找{{1}的过程}}

然后在动态编程之后,只需找到词典编号最大的项目名称集,并将其从原始项目集中排除。剩下的项目就是答案。

这是我在C ++ 14中接受的难看的丑陋代码,大部分内容是处理麻烦的I / O内容,请告诉我,如果不清楚,我可以提供一些例子来详细说明更多。

DP(i)

答案 1 :(得分:0)

根据您指定的问题,如果我告诉您不需要告诉我产品的订单或名称,您只需要告诉我 -
 的数量 将更改的产品值 你的回答是什么?

基本上问题已经减少到以下陈述 -

您将获得一个数字列表,并且您希望对列表进行一些更改,以使这些数字按顺序递增。但是您希望对列表中各个元素所做的更改最小化。

你会如何解决这个问题?

如果您在所拥有的数字列表中找到最长的增加子序列,那么您只需要减去 列表的长度< / em>来自 LIS 值。

你为什么这么问?

好吧因为如果你想要对列表做出的更改次数最少,那么如果我按原样保留最长的增加子序列并更改其他值,我肯定会获得最佳答案。

让我们举个例子 -

我们有 - 2 10 4 6 8

对此列表进行了多少更改?

最长的子序列长度为 - 4。 因此,如果我们保留4个项目值并更改其他剩余值,那么我们只需要更改5(列表长度) - 4 = 1值。

现在解决原始问题,您需要打印产品名称。如果您排除LIS中的元素,您应该得到答案 但是等等! 当你有许多具有相同LIS长度的子序列时会发生什么?您将如何选择按字典顺序排列的最小答案?

那你为什么不考虑LIS本身呢?这应该足以让你开始正确吗?