zoukankan      html  css  js  c++  java
  • hdu6196 happpy happy happy (meet in middle + 剪枝)

    题意

      从1到n共计n(<=90)个物品,每个物品有一个价值a[i],儿子和爸爸轮流做游戏,儿子先手。儿子每次选价值最大的{最左边,最右边}的物品,如果价值一样大, 则选取最左边的物品。 爸爸每次可以取最左边或最右边的物品。 
      问你,爸爸想要输(价格严格小),而且差值尽可能少的最小差值是多少。

    分析

      首先n<=90,所以应该是个搜索,而不是dp

      我们来考虑一下为什么不是dp,而只能搜索?

      如果题目改成爸爸想让差值最大或者最小,那么显然可以直接dp,而这里实际上求一个大于0的最小差值,相当于在所有可能差值的中间,自然无法dp了

      直接dfs显然时间效率是$O(2^{45})$无法接受,这里可以考虑meet in middle,我们将90个物品分成44个和46个

      对于里面的部分,我们可以先dfs求出所有可能差值,然后再dfs外面,如果当前长度<=44了,那么我们就可以将当前结果在之前第一次dfs的结果里二分,找到大于0的最小差值

      这样时间复杂度就是$O(2^{23}*log(2^{22}))$

      这样的时间复杂度感觉勉强是可以接受的,但问题是,2^22这么多取值我们无法存进数组中

      那我们只有加大两部分的差值了,比如提前预处理长度为30的结果,再去对长度为50的dfs

      但这样的话,对50的dfs部分时间复杂度是$O(2^{25}*log(2^{15}))$,我们必须剪枝

      对于dfs(l,r),有两个剪枝:

        如果当前差值+[l,r]最大差值<=0,这说明这种情况儿子始终无法赢,直接return

        如果当前差值+[l,r]最小差值>=ans,这说明这种情况下的结果不会比ans更优,直接return

      加上这两个剪枝就可以1800ms通过了  

  • 相关阅读:
    拥抱函数式编程 I
    关于CMS的那点事 I
    常用正规表达式
    javascript source map 的使用
    架构师修炼 后记
    CSS 天坑 I
    架构师修炼 III
    架构师修炼 II
    win10,VM14 安装cnetos6.9 虚拟机黑屏和只有光标闪烁解决办法
    C/C++数组初始化
  • 原文地址:https://www.cnblogs.com/wmrv587/p/7515782.html
Copyright © 2011-2022 走看看