Redian新闻
>
一道面试题——取珠宝
avatar
一道面试题——取珠宝# JobHunting - 待字闺中
h*6
1
某公司的电面题,以前没见过,觉得有点意思,就贴在这里。
一些珠宝排成一行,每个珠宝都有一个正整数价值。两人玩一个游戏,每人每回合可以从任意一端取一个珠宝,直到全部珠宝取完,所取得珠宝总价值最大的获胜。已知每个珠宝的价值,假设两人都特别聪明,求先取的人最多能取到多少价值的珠宝?
自定义函数参数和返回值。
avatar
d*e
2
觉得总是取剩下里面最大价值的不就赢了?

以从任意一端取一个珠宝,直到全部珠宝取完,所取得珠宝总价值最大的获胜。已知每
个珠宝的价值,假设两人都特别聪明,求先取的人最多能取到多少价值的珠宝?

【在 h**6 的大作中提到】
: 某公司的电面题,以前没见过,觉得有点意思,就贴在这里。
: 一些珠宝排成一行,每个珠宝都有一个正整数价值。两人玩一个游戏,每人每回合可以从任意一端取一个珠宝,直到全部珠宝取完,所取得珠宝总价值最大的获胜。已知每个珠宝的价值,假设两人都特别聪明,求先取的人最多能取到多少价值的珠宝?
: 自定义函数参数和返回值。

avatar
z*n
3
只能从两端取。。。
感觉是个dp题

【在 d**e 的大作中提到】
: 觉得总是取剩下里面最大价值的不就赢了?
:
: 以从任意一端取一个珠宝,直到全部珠宝取完,所取得珠宝总价值最大的获胜。已知每
: 个珠宝的价值,假设两人都特别聪明,求先取的人最多能取到多少价值的珠宝?

avatar
t*a
4
O(n^2) DP solution here:
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include
int a[] = {4,6,1,7,2,10,8,5,3,9};
const int n = 10;
int sum[n][n];
int best[n][n];
int game(int a[], int start, int stop) {
if (start > stop) {
return 0;
} else if (best[start][stop]!=-1) {
return best[start][stop];
} else {
int s1 = sum[start+1][stop] - game(a, start+1, stop) + a[start];
int s2 = sum[start][stop-1] - game(a, start, stop-1) +
avatar
y*d
5
这是 2^n 吧

【在 t****a 的大作中提到】
: O(n^2) DP solution here:
: #ifdef HAVE_CONFIG_H
: #include
: #endif
: #include
: #include
: int a[] = {4,6,1,7,2,10,8,5,3,9};
: const int n = 10;
: int sum[n][n];
: int best[n][n];

avatar
t*a
6
O(n^2)
fill best[n][n]
avatar
y*d
7
u r right

【在 t****a 的大作中提到】
: O(n^2)
: fill best[n][n]

avatar
d*e
8
可不可以解释一下思路?
我运行出来的结果是37,那每一步是怎么取的呢?
因为每人取五个,我猜37 = 10 + 9 + 8 + 7 + 3,或者类似的。问题是第一个人取了
10,第二个怎么可能不取9?
谢谢。

【在 t****a 的大作中提到】
: O(n^2) DP solution here:
: #ifdef HAVE_CONFIG_H
: #include
: #endif
: #include
: #include
: int a[] = {4,6,1,7,2,10,8,5,3,9};
: const int n = 10;
: int sum[n][n];
: int best[n][n];

avatar
z*n
9
best(i,j)=max(a[i]+best(i-2,j), a[i]+best(i-1),(j-1),a[j]+best(i-1)(j-1), a[
j]+best(i, j-2))
初始情况就是如果i==j,return a[i];如果i>j, return 0。
调用时候调用best(0,n-1)。
思路就是一共就4种取法,你取最左,对手取次左;你取最左,对手取最右;你取最右,
对手取最左;你取最右,对手取次右
这四种情况,你都递归算一下剩余子问题的最优方案,最优的那个就是了

【在 d**e 的大作中提到】
: 可不可以解释一下思路?
: 我运行出来的结果是37,那每一步是怎么取的呢?
: 因为每人取五个,我猜37 = 10 + 9 + 8 + 7 + 3,或者类似的。问题是第一个人取了
: 10,第二个怎么可能不取9?
: 谢谢。

avatar
h*6
10
to Done:
你没有理解题意,只能从两端开始取,也就是第一轮只能取4或9,不能取10。
to zysxqn:
双方各取一次确实是四种取法,不过并不是在这四种情况中找最优,而是每两种情况
找出最差再找最优。因为对手的最优,是我方的最差。
avatar
z*n
11
感觉题目问的是最多有可能得到多少,这样不是应该理解成如果对手很傻,或者对手配
合的情况下?

【在 h**6 的大作中提到】
: to Done:
: 你没有理解题意,只能从两端开始取,也就是第一轮只能取4或9,不能取10。
: to zysxqn:
: 双方各取一次确实是四种取法,不过并不是在这四种情况中找最优,而是每两种情况
: 找出最差再找最优。因为对手的最优,是我方的最差。

avatar
f*g
12
不能保证先取的总赢吧,比如131, 13131,先取得肯定输
avatar
z*n
13
题目只是问先取的最多能得到多少珠宝,没有要求赢,也没说对方什么策略
所以我的理解是,假设对方很傻,完全配合你,根据输入的珠宝排列,最多能得到多少
珠宝

【在 f*********g 的大作中提到】
: 不能保证先取的总赢吧,比如131, 13131,先取得肯定输
avatar
b*a
14
我覺得這個應該是用剪枝的那種思路把,就是假設對手也總會選擇最優解

【在 z****n 的大作中提到】
: 题目只是问先取的最多能得到多少珠宝,没有要求赢,也没说对方什么策略
: 所以我的理解是,假设对方很傻,完全配合你,根据输入的珠宝排列,最多能得到多少
: 珠宝

avatar
B*5
15
没说对方的策略,但是说了对方足够聪明,所以我觉得对方总会去他们最优的方法。。。

【在 z****n 的大作中提到】
: 题目只是问先取的最多能得到多少珠宝,没有要求赢,也没说对方什么策略
: 所以我的理解是,假设对方很傻,完全配合你,根据输入的珠宝排列,最多能得到多少
: 珠宝

avatar
d*e
16
谢谢。
我的确没看清 -_-!
当时没看到那“一端”两个字.
再仔细研究一下。

【在 h**6 的大作中提到】
: to Done:
: 你没有理解题意,只能从两端开始取,也就是第一轮只能取4或9,不能取10。
: to zysxqn:
: 双方各取一次确实是四种取法,不过并不是在这四种情况中找最优,而是每两种情况
: 找出最差再找最优。因为对手的最优,是我方的最差。

avatar
j*u
17
珠宝价值 p_1, p_2, ..., p_n
denote:
sum(i ,j) = p_i + p_i+1 + ... + p_n
recursion:
先拿的是最多是总数减去后拿的最多->
best(i, j) = max{ sum(i, j) - best(i+1, j), sum(i, j) - best(i,j-1) }
=sum(i, j) - min{ best(i+1, j), best(i, j-1) }
所以先拿的策略是两种情况中让后拿的拿得最少,下面这些是要算的:
best(1, n)

best(2, n)--best(1, n-1)
best(3, n)--best(2, n-1)--best(1, n-2)
...
best(i, n)--best(i-1, n-1)--best(2, n-(i-2))--best(1, n-(i-1))
...
best(n-1, n)--best(n-2, n-1) ................ best(1, 2)
p_n p_n-1
avatar
h*k
18
不错,我有个另外的思路,不需要计算sum(i,j).
best(i,j) = max( a[i] + min( best(i+2,j), best(i+1,j-1) ),
a[j] + min( best(i+1,j-1), best(i, j-2) ) );
a[i], a[j] 分别指第i个和第j个珠宝的价值。best(i,j)指从第i个到第j个珠宝中选择
的最多的珠宝价值。
选择的含义是,如果选择了a[i],那么对手只能选择a[i+1]或者a[j],而且对手肯定会
选择一种方案,让你之后的收益最小,所以选择a[i]的最大收益是a[i]+min( best(i+2
,j), best(i+1,j-1) );相似的我们可以知道选择a[j]后的最大可能收益。
终止条件是,if( i == j ) best(i,j) = a[i];
if( i+1 == j ) best(i,j) = max(a[i],a[j]);
时间复杂度还是O(n^2)。但是可能会比junwu的算法稍微快一些,因为迭代的时候是步
长是2,而junwu的算法的步长是1。

【在 j***u 的大作中提到】
: 珠宝价值 p_1, p_2, ..., p_n
: denote:
: sum(i ,j) = p_i + p_i+1 + ... + p_n
: recursion:
: 先拿的是最多是总数减去后拿的最多->
: best(i, j) = max{ sum(i, j) - best(i+1, j), sum(i, j) - best(i,j-1) }
: =sum(i, j) - min{ best(i+1, j), best(i, j-1) }
: 所以先拿的策略是两种情况中让后拿的拿得最少,下面这些是要算的:
: best(1, n)
:

相关阅读
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。