求昨天有道的一个题目的思路

windsting 2010-06-15 12:46:20
恕我愚钝,我甚至没有意识到这个题目的难度跟分数是匹配的,
感觉应该很简单,但就是做不出来。

我不要解答代码,描述性的文字、伪码都可以,提问目的:
1、让我明白这题目有多难,
2、让我知道解答的大致思路。

分数分配按回复内容让我明白的程度,(主观地)进行分配,谢谢各位。

描述
搞程序竞赛的小朋友爱打牌,爱打牌的小朋友爱拱猪。
这次竞赛有k个小朋友参加,他们计划一起拱猪!显然一副普通的扑克不够用,所以他们设计了一副特殊的扑克,这副扑克有n张牌,每张牌都有一个整数。
每一局游戏结束后每张牌都会被某一个小朋友获得,并且每个小朋友都至少获得一张牌。第i个小朋友的得分为他获得的所有牌上的数字之积,计做Si。一局游戏的总得分为所有小朋友的得分之和。你的任务是求一局游戏可能的最大得分。
输入
第一行为一个正整数T,表示数据组数。
接下来每组数据分为两行,第一行为空格隔开的两个正整数n,k ,表示这副扑克有n张牌,一共有k个小朋友参加游戏。
第二行为空格隔开的n个整数,表示n张牌上的数字。

其中牌上的数字范围是[-5000, 5000], T<=500
小数据:1 <= n, k <= 100。250分,时限1s。
大数据:1 <= n, k <= 2000。150分,时限10s。
输出
一个整数,代表可能的最大得分。
样例输入
2
12 6
-7 -6 -5 -4 -3 -2 -1 1 2 3 4 5
12 6
4 3 1 2 0 -1 -3 -4 -5 -2 -6 -7
样例输出
50397
20165
提示
样例解释:
样例1:-7*-6*-5*-4*3*5*4 -1,1,2,-2,-3单独一组。
样例2:-7*-6*-5*-4*-3*-2*4 3,2,1,0,-1单独一组。
...全文
433 24 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
windsting 2010-06-27
  • 打赏
  • 举报
回复
说到底是我基础太差,始终不能弄明白这题目考察的是什么,
看了官方的解题思路也没弄明白,所以应该说没有满意答案,
在这里谢谢 TeaTimeL 的热心解释,但我真的没达到提问目的,
作为无满意答案的结果结贴,显然对热心回复的同学不太公平,
我只有抱歉了。

看完手上计划看的书,我要开始看《算法导论》了,
因为我恍惚觉得这样的问题的答案应该可以在里面得到答案。

今天看了看有到难题晋级赛的题目,我就没心思了,
以我目前的能力,根本不可能解答出来的。
qujunde 2010-06-17
  • 打赏
  • 举报
回复
可能是我太笨我到最后也没看到游戏规则的说明 到底怎样记分??
windsting 2010-06-17
  • 打赏
  • 举报
回复
深夜一顶,顺便说一句,这题目里面隐含了一个问题,就是大数乘法,
测试数据中的n、k两个数字的差,大体上是乘法中的因子数量,
就算使用小数据测试,n、k都在100之下,只要两个数字的差略大,
就无法使用常见的数据类型(double、longlong都不行)进行表示,
但这属于实现层面的问题,可以不做讨论,下面给组数据和答案,
建议有思路的同学自己编码测试一下,必有收获。

70 60
9446 -1407 -5279 4070 6671 -1480 -9305 1839 2057 -3757 3715 5647 8323 8845 -5581 1539 5408 853 -5251 2437 8052 -7650 -8685 -5071 4714 -9833 8922 -1688 424 -9348 -3253 -3060 -3596 -4017 -3047 -6153 -9866 -702 -9453 200 3614 -6153 -8658 -7558 3048 -9654 1115 -5731 -2304 -8246 5789 -7777 -5661 -3886 -4926 1288 -9181 -9809 -4443 5423 2165 -7264 635 -5974 -7096 4102 -2158 -4895 -3220 -4517

答案:
51696590711279437472246261385178980487895384

直接复制粘贴到一个不换行的文本编辑器中查看即可,我粘贴的时候没有回车,
最好使用命令行的输入重定向输入,否则这么多数字的输入过程,将是一场噩梦。
fanster28_ 2010-06-17
  • 打赏
  • 举报
回复
思路就是贪心,不过需要枚举几种情况,最好记录最大值,否则容易漏解

另外,此题要处理大数乘法,加法,这个也是难点(效率难上去,难不成还写fft大数相乘)
Gary@Tokyo 2010-06-16
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 defonds 的回复:]
引用 3 楼 lthyxy 的回复:
有高手在写代码了,你等着~!
搬个凳子围观。
[/Quote]
搞算法啊,我也搬个板凳围观
Defonds 2010-06-16
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 lthyxy 的回复:]
有高手在写代码了,你等着~!
[/Quote]搬个凳子围观。
cattycat 2010-06-16
  • 打赏
  • 举报
回复
想了下,把绝对值最小的k-1个赋值给k-1个小朋友,然后检测剩下的数中是否有0,如果有0,说明至少有k个0了,所以把剩下的数中的0再给前k-1中任意一个,如果剩下的数中没有0,再判断负数的个数,负数是偶数个,那已经可以满足要求了。如果有奇数个负数,需要把一个负数交换出去,或从外面交换一个负数进来。
然后从剩下的数中选择绝对值最小的两个数,一个是正数,一个是负数。
如果前k-1个再有负数,只需要把正数和前k-1个中绝对值最大的负数交换。因为这时求和的时候这个正数最后是正的。
如果前k-1个没有负数,则把负数交换出去,和前k-1个中最大的那个。

这样能把第二种给考虑进去。但似乎太烦了。还是希望能看到解题报告中的思路。
tulipcaicai 2010-06-16
  • 打赏
  • 举报
回复
不懂,帮顶,关注楼主
品茶 2010-06-16
  • 打赏
  • 举报
回复
总结一下

在n张牌poker[0]到poker[n-1]中找出k-1张min(abs(poker[i]))
发给前k-1个小朋友boy[0]到boy[k-2]

计算最大得分
剩余n-k+1张牌有偶数张负数牌则可计算最终结果(无视剩余n-k+1张牌中的0值牌,因为这时boy[0]到boy[k-2]都是0值牌,可以分配剩余0值牌到其中任意一个)
若有奇数张,则在boy[0]到boy[k-2]中找出绝对值最大数a(非唯一情况下负数优先),在剩余n-k+1张牌中找出绝对值最小数b(非唯一情况下正数优先)
若a*b<0则交换ab计算结果
若a*b>=0则a*=b去掉b计算结果
品茶 2010-06-16
  • 打赏
  • 举报
回复
第三步 计算最大得分
剩余n-k+1张牌有偶数张负数牌则可计算最终结果
若有奇数张,则在boy[0]到boy[k-2]中找出绝对值最大数a(非唯一情况下负数优先),在剩余n-k+1张牌中找出绝对值最小数b(非唯一情况下正数优先)
若a*b<0则交换ab计算结果
若a*b>=0则a*=b去掉b计算结果
windsting 2010-06-16
  • 打赏
  • 举报
回复
To:#14
题目没有说每个数字只出现一次,所以,如果NUM0[]中有多个元素,你这个方法就有问题了,
是最主要的问题不在于此,就算是有多个0,可以先把所有的0分配掉,就解决了你这个纰漏,
但是剩下的问题才是最关键的,就像你在#15给出的思路,看了题目之后,最直接的就是这个思路,
但是你看示例中的第二组数据,这是你的思路没有解决的。
事实上,我看了题目之后所能做出来的,就是#15的这个解,但是很明显,这是个WrongAnswer。
liutengfeigo 2010-06-16
  • 打赏
  • 举报
回复
。。。高手还不出现???
品茶 2010-06-16
  • 打赏
  • 举报
回复
简化一下

在n张牌poker[0]到poker[n-1]中找出k-1张min(abs(poker[i]))
发给前k-1个小朋友boy[0]到boy[k-2]

接着做第三步
品茶 2010-06-16
  • 打赏
  • 举报
回复
第一步 准备
将n张牌poker[n]分为三部分:负数数组NUM_1[],NUM0[]和正数数组NUM1[]

第二步 保证每个小朋友都有牌
联合NUM_1和NUM1,按绝对值大小找出最小的k-2个数
分给小朋友boy[0]至boy[k-3]
NUM0为空即没有0数值牌时,再找出绝对值最小的一个数给boy[k-2]
NUM0非空,则boy[k-2]为0

第三步 计算最大得分
剩余n-k+1张牌有偶数张负数牌则可计算最终结果
若有奇数张,则
在剩余牌中找出最大负数a,在boy[0]到boy[k-2]中找出最大数b
b>1则交换a和b计算结果(即a为加数,b和剩余n-k张牌相乘的结果也为加数)
b<=1则在boy[0]到boy[k-2]中找出最小数c则c*=a去掉a计算结果
windsting 2010-06-15
  • 打赏
  • 举报
回复
To:#8,我的思路不够,没能解决“调整绝对值最大的序列之积和剩余数字”这个问题,
To:#9,这个题目,除了乘积,还有一个求和,不是想象中的那样,比如上一句这个问题,
就很难总结一个一般的规律并作出解决。
cattycat 2010-06-15
  • 打赏
  • 举报
回复
4楼的和楼主的想法都是贪心策略,我也想不出更好的办法。
可以先把绝对值最小的k个数分给k个小朋友,为了不漏解,然后剩下的可以和每一个相乘,比较最大的。这个应该不会漏解吧。应该能证明这种方式能求得最大的,不会有两个以上小朋友有更多的数这种情况。
  • 打赏
  • 举报
回复
呵呵,楼主既然有了思路,估计代码也不在话下了吧
weixiaoshashou 2010-06-15
  • 打赏
  • 举报
回复
怎么初看起来有点像最大K乘的问题,不过细看一下又不是了。哎难啊。
chin_chen 2010-06-15
  • 打赏
  • 举报
回复
ding
windsting 2010-06-15
  • 打赏
  • 举报
回复
#4的,我的思路跟你一样,但你看看示例中的第二个,这个特殊情况就很难处理,
单单处理这一个例子还可以,但想总结这个特殊情况的一般状态,就很难了,
我写的代码可以得到第一个结果,但是对于第二个,除非专门针对这个例子写,
但又无法解决这个情况的其它可能,所以,我最后一次都没有提交过。

#3,我发帖说了,不要代码,要思路,因为我不是很聪明哪种,
有时候,拿到答案看过之后,都不知道人家是怎么得到这个答案的,
这样无法达到学习目的,就算这次抄了一个答案,但是如果不能理解,
下次遇到很可能也会忘记了,所以我选择要一个思路,谢谢。
加载更多回复(4)

65,186

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧