Coins in a Line II
ref: http://www.lintcode.com/en/problem/coins-in-a-line-ii/#
有个博客说的挺好的,比九章自己写的清楚
http://www.cnblogs.com/theskulls/p/4963317.html
- 意思是这样的:
如果我们在第i个位置,那么我们有两种选择,我们要选取里面更大的
1. 我们只拿一个values[i],那么对方也是很机智的,他会试图给我们最差的结果,会选择拿一个[i+1]或者两个[i+1]&[i+2],试图给我们留更小的值,所以我们自动拿到了dp[i+2](对方拿一个)和dp[i+3](对方拿了两个)中比较小的那个,此时dp[i]_1 = values[i] + min{dp[i+2], dp[i+3]};
2. 我们拿了两个数, values[i]&values[i+1],和上一种可能里一样,机智的对手会给我们剩下dp[i+3]和dp[i+4]里比较小的那个, 此时dp[i]_1 = values[i]+values[i+1]+min{dp[i+3], dp[i+4]};
所以结果是dp[i] = max{dp[i]_1, dp[i]_2}
- 我们可以想象是从右往左推导,因为前面的结果需要确定的后面的结果
- 初始化的问题:首先我们可以人工分析出,如果有两个及以下的结果,就是都选了,如果有三个数的时候,就从左往右选前两个,因为就算不能赢也尽量给对手少点。但是到四个的时候,这个就不一定了,要根据具体的数字分析,我们不能强行初始化了。但是dp的时候又需要用到dp[i+4],所以只能多加一格,初始化成0,来辅助dp
感觉理解还是不够深入,以后多做几遍可能感觉会好一点
1 public boolean firstWillWin(int[] values) { 2 int len = values.length; 3 if(len == 0) { 4 return false; 5 } 6 if(len == 1 || len == 2) { 7 return true; 8 } 9 int[] dp = new int[len + 1]; 10 int allSum = 0; 11 dp[len] = 0; 12 dp[len - 1] = values[len - 1]; 13 dp[len - 2] = values[len - 2] + values[len - 1]; 14 dp[len - 3] = values[len - 3] + values[len - 2]; 15 allSum = dp[len - 3] + values[len - 1]; 16 for(int i = len - 4; i >= 0; i--) { 17 allSum += values[i]; 18 dp[i] = values[i] + Math.min(dp[i + 2], dp[i + 3]); 19 dp[i] = Math.max(dp[i], values[i] + values[i + 1] + Math.min(dp[i + 3], dp[i + 4])); 20 } 21 return dp[0] > allSum - dp[0]; 22 }