LeetCode 1563. 石子游戏 V

题目链接:LeetCode 1563. 石子游戏 V

题意:

      几块石子 排成一行 ,每块石子都有一个关联值,关联值为整数,由数组 stoneValue 给出。

游戏中的每一轮:Alice 会将这行石子分成两个 非空行(即,左侧行和右侧行);Bob 负责计算每一行的值,即此行中所有石子的值的总和。Bob 会丢弃值最大的行,Alice 的得分为剩下那行的值(每轮累加)。如果两行的值相等,Bob 让 Alice 决定丢弃哪一行。下一轮从剩下的那一行开始。

只 剩下一块石子 时,游戏结束。Alice 的分数最初为 0 。

返回 Alice 能够获得的最大分数 。

 

解题思路:

   动态规划

 

采用递归加记忆化搜索实现动态规划

class Solution {
	public $dp = array();
    /**
     * @param Integer[] $stoneValue
     * @return Integer
     */
    function stoneGameV($stoneValue) {
    	$n = count($stoneValue);
    	for($i = 0; $i < $n; $i++) {
    		for($j = 0; $j < $n; $j++) {
    			$this->dp[$i][$j] = -1;
    		}
    	}
    	return $this->dfs(0, $n-1, $stoneValue);
    }
    function dfs($l, $r, $arr) {
    	if($l == $r) {
    		return 0;
    	}
    	if($this->dp[$l][$r] != -1) {
    		return $this->dp[$l][$r];
    	}
    	$sum = 0; $ans = 0; $cur = 0;
    	for($i = $l; $i <= $r; $i++) {
    		$sum += $arr[$i];
    	}
    	for($mid = $l; $mid < $r; $mid++) {
    		$cur += $arr[$mid];
    		$now = 0;
    		if($cur < $sum - $cur) {
    			$now = $cur + $this->dfs($l, $mid, $arr);
    		} else if($cur > $sum - $cur){
    			$now = $sum - $cur + $this->dfs($mid+1, $r, $arr);
    		} else {
    			$now = $cur + max($this->dfs($l, $mid, $arr), $this->dfs($mid+1, $r, $arr));
    		}
    		$ans = max($ans, $now);
    	}
    	return $this->dp[$l][$r] = $ans;
    }
}

注意:O(N^3)复杂度高,超时代码

class Solution {

    /**
     * @param Integer[] $stoneValue
     * @return Integer
     */
    function stoneGameV($stoneValue) {
    	$dp = array();$sum = array();
    	$n = count($stoneValue);
    	for($i = 0; $i < $n; $i++) {
    		for($j = 0; $j < $n; $j++) {
    			$dp[$i][$j] = 0;
    		}
    	}
    	$sum[0] = $stoneValue[0];
    	for($i = 1; $i < $n; $i++) {
    		$sum[$i] = $sum[$i-1] + $stoneValue[$i];
    	}
    	for($len = 0; $len <= $n; $len++) {
    		for($l = 0; $l + $len < $n; $l++) {
    			$r = $l + $len;
    			for($mid = $l; $mid < $r; $mid++) {
    				if($l > $mid || $mid + 1 > $r) {
    					break;
    				}
    				$lv = $sum[$mid] - ($l > 0 ? $sum[$l-1]:0);
    				$lr = $sum[$r] - $sum[$mid];
    				if($lv == $lr) {
    					$dp[$l][$r] = max($dp[$l][$r], $lv+max($dp[$l][$mid], $dp[$mid+1][$r]));
    				} else if($lv > $lr){
    					$dp[$l][$r] = max($dp[$l][$r], $dp[$mid+1][$r] + $lr);
    				} else {
    					$dp[$l][$r] = max($dp[$l][$r], $dp[$l][$mid] + $lv);
    				}
    			}
    		}
    	}
    	return $dp[0][$n-1];
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值