腾讯面试算法题

H_Clong 2015-08-23 06:13:35
两个人(A,B)参与一个游戏,规则如下: 1)一个随机的整数数列有偶数个数,a1,a2,…a2n 2)A先从数列取数,但只能从两头取,a1 or a2n 3)然后B取数,也是只能从剩下的两头取,依此类推,两个人轮流,都只能从两头取4)最后谁手里的数和最大赢。
...全文
449 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
H_Clong 2015-08-24
  • 打赏
  • 举报
回复
引用 9 楼 忘世麒麟的回复:
去年文思海辉在CSDN上发起一个音雄会:A B依次删除一串字符中的字母,要保证A赢.和这道题是类似的,而且当时人家出家10w悬赏.而腾讯干脆拿出来做面试题了.真是服了.
腾讯说的是硬币!50枚面值不同排成一排!两头取保证大于等于对手!
H_Clong 2015-08-24
  • 打赏
  • 举报
回复
引用 9 楼 忘世麒麟的回复:
去年文思海辉在CSDN上发起一个音雄会:A B依次删除一串字符中的字母,要保证A赢.和这道题是类似的,而且当时人家出家10w悬赏.而腾讯干脆拿出来做面试题了.真是服了.
腾讯说的是50枚硬币排成一排,面额是多少忘记了!也是两头取保证自己不会输,我觉得和这个一样就这样写了!
H_Clong 2015-08-24
  • 打赏
  • 举报
回复
引用 8 楼 Qt讷讷熊的回复:
题目是楼主自己描述的吧. 原题这样的话可谓描述不清. 应该是设计一种策略, 比如代表A去玩这个游戏, 如何取得总数最大. 极端情况下, 有个数字 ax 比其他数字之和还要大, 那策略就是怎么拿到这个数字而不让对方拿到了. 这种情况比如数字剩余 5,100,2 的时候, 就绝对不是在两端挑一个大的来拿这么简单了.
嗯嗯,是的,应该是随机的顺序序列!保证自己不会小于对手就算赢了!
忘世麒麟 2015-08-24
  • 打赏
  • 举报
回复
去年文思海辉在CSDN上发起一个音雄会:A B依次删除一串字符中的字母,要保证A赢.和这道题是类似的,而且当时人家出家10w悬赏.而腾讯干脆拿出来做面试题了.真是服了.
Qt讷讷熊 2015-08-24
  • 打赏
  • 举报
回复
题目是楼主自己描述的吧. 原题这样的话可谓描述不清. 应该是设计一种策略, 比如代表A去玩这个游戏, 如何取得总数最大. 极端情况下, 有个数字 ax 比其他数字之和还要大, 那策略就是怎么拿到这个数字而不让对方拿到了. 这种情况比如数字剩余 5,100,2 的时候, 就绝对不是在两端挑一个大的来拿这么简单了.
zilaishuichina 2015-08-24
  • 打赏
  • 举报
回复
这其实就是一颗2叉博弈树:举个数量少点的例子: 1,3,5,7,8,6,4,2 如下所示

A拿:       1               2
         /   \           /   \
B拿:   3       2       1       4
      / \     / \     / \     / \
A拿: 5   2   3   4   3   4   1   6
    / \ / \ / \ / \ / \ / \ / \ / \
B拿:2 7 4 5 4 5 3 6 4 5 3 6 3 6 1 8
以此类推
Guanglew 2015-08-23
  • 打赏
  • 举报
回复
楼主是不是把题目理解错了?
H_Clong 2015-08-23
  • 打赏
  • 举报
回复
引用 6 楼 H_Clong的回复:
[quote=引用 5 楼 Guanglew的回复:]楼主是不是把题目理解错了?
没有吧!确实是这样的[/quote] 不是动态规划做么?
H_Clong 2015-08-23
  • 打赏
  • 举报
回复
引用 5 楼 Guanglew的回复:
楼主是不是把题目理解错了?
没有吧!确实是这样的
H_Clong 2015-08-23
  • 打赏
  • 举报
回复
引用 3 楼 iyomumx的回复:
设序列只剩下a[x]开头到a[y]结尾,令f(x,y)为该情况下先手方能取得的最优分数,g(x,y)为此时后手方能取得的分数 则先手方有两种选择: 1.选a[x],可以得到 a[x] + g(x + 1, y) 分,对手得到 f(x + 1, y) 分,分差v1 = a[x] + g(x + 1, y) - f(x + 1, y) 2.选a[y],可以得到 a[y] + g(x, y - 1) 分,对手得到 f(x, y - 1) 分,分差v2 = a[y] + g(x, y - 1) - f(x, y - 1) 选分差大的那种,即
f(x, y) = a[x] + g(x + 1, y) ( v1 >= v2)
        = a[y] + g(x, y - 1) ( v1 <  v2)
g(x, y) = f(x - 1, y)        ( v1 >= v2)
        = f(x, y - 1)        ( v1 >= v2)
先写个递归搜索理一下思路:
template <typename RanIt>
pair<typename iterator_traits<RanIt>::value_type, typename iterator_traits<RanIt>::value_type> Select(RanIt start, RanIt end)
{
    if (distance(start, end) == 1)
    {
        return make_pair(*start, 0);
    }
    auto l = *start;
    const auto & sl = Select(next(start), end);
    auto r = *--end;
    const auto & sr = Select(start, end);
    auto v1 = l + sl.second - sl.first;
    auto v2 = r + sr.second - sr.first;
    if (v1 >= v2)
    {
        return make_pair(l + sl.second, sl.first);
    }
    else
    {
        return make_pair(r + sr.second, sr.first);
    }
}
然后就可以简单改写成递推式:
pair<int, int> GetResult(const vector<int>& values)
{
    //i , j : 从第i个数开始长度为j的序列
    //table[i][j] : (先手取得数字和,后手取得数字和)
    pair<int, int> ** table = new pair<int, int>*[values.size()];
    for (int i = 0; i < values.size(); ++i)
    {
        table[i] = new pair<int, int>[values.size() - i];
        table[i][0] = make_pair(values[i], 0);
    }
    for (int j = 1; j < values.size(); ++j)
    {
        for (int i = 0; i + j < values.size(); ++i)
        {
            int l = values[i];
            int r = values[i + j];
            const pair<int, int>& sl = table[i + 1][j - 1];
            const pair<int, int>& sr = table[i][j - 1];
            int v1 = l + sl.second - sl.first;
            int v2 = r + sr.second - sr.first;
            if (v1 >= v2)
            {
                table[i][j] = make_pair(l + sl.second, sl.first);
            }
            else
            {
                table[i][j] = make_pair(r + sr.second, sr.first);
            }
        }
    }
    pair<int, int> result = table[0][values.size() - 1];
    for (int i = 0; i < values.size(); ++i)
    {
        delete[] table[i];
    }
    delete[] table;
    return result;
}
大概是这样吧
没学模板!
iyomumx 2015-08-23
  • 打赏
  • 举报
回复
设序列只剩下a[x]开头到a[y]结尾,令f(x,y)为该情况下先手方能取得的最优分数,g(x,y)为此时后手方能取得的分数 则先手方有两种选择: 1.选a[x],可以得到 a[x] + g(x + 1, y) 分,对手得到 f(x + 1, y) 分,分差v1 = a[x] + g(x + 1, y) - f(x + 1, y) 2.选a[y],可以得到 a[y] + g(x, y - 1) 分,对手得到 f(x, y - 1) 分,分差v2 = a[y] + g(x, y - 1) - f(x, y - 1) 选分差大的那种,即
f(x, y) = a[x] + g(x + 1, y) ( v1 >= v2)
        = a[y] + g(x, y - 1) ( v1 <  v2)
g(x, y) = f(x - 1, y)        ( v1 >= v2)
        = f(x, y - 1)        ( v1 >= v2)
先写个递归搜索理一下思路:
template <typename RanIt>
pair<typename iterator_traits<RanIt>::value_type, typename iterator_traits<RanIt>::value_type> Select(RanIt start, RanIt end)
{
    if (distance(start, end) == 1)
    {
        return make_pair(*start, 0);
    }
    auto l = *start;
    const auto & sl = Select(next(start), end);
    auto r = *--end;
    const auto & sr = Select(start, end);
    auto v1 = l + sl.second - sl.first;
    auto v2 = r + sr.second - sr.first;
    if (v1 >= v2)
    {
        return make_pair(l + sl.second, sl.first);
    }
    else
    {
        return make_pair(r + sr.second, sr.first);
    }
}
然后就可以简单改写成递推式:
pair<int, int> GetResult(const vector<int>& values)
{
    //i , j : 从第i个数开始长度为j的序列
    //table[i][j] : (先手取得数字和,后手取得数字和)
    pair<int, int> ** table = new pair<int, int>*[values.size()];
    for (int i = 0; i < values.size(); ++i)
    {
        table[i] = new pair<int, int>[values.size() - i];
        table[i][0] = make_pair(values[i], 0);
    }
    for (int j = 1; j < values.size(); ++j)
    {
        for (int i = 0; i + j < values.size(); ++i)
        {
            int l = values[i];
            int r = values[i + j];
            const pair<int, int>& sl = table[i + 1][j - 1];
            const pair<int, int>& sr = table[i][j - 1];
            int v1 = l + sl.second - sl.first;
            int v2 = r + sr.second - sr.first;
            if (v1 >= v2)
            {
                table[i][j] = make_pair(l + sl.second, sl.first);
            }
            else
            {
                table[i][j] = make_pair(r + sr.second, sr.first);
            }
        }
    }
    pair<int, int> result = table[0][values.size() - 1];
    for (int i = 0; i < values.size(); ++i)
    {
        delete[] table[i];
    }
    delete[] table;
    return result;
}
大概是这样吧
夏殇末 2015-08-23
  • 打赏
  • 举报
回复
没怎么懂你的意思
H_Clong 2015-08-23
  • 打赏
  • 举报
回复
对DP算法没理解到家 只能有个大致的思路 但是总有一两点想不通

65,186

社区成员

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

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