我一直在浏览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
我不是要求确切的解决方案,但是,我该如何处理问题
提前致谢。
答案 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本身呢?这应该足以让你开始正确吗?