矩阵取数游戏
https://www.nowcoder.com/practice/413183818ce5493b9372986ddfe5df28
import java.math.BigInteger;
import java.util.*;
/**
* NC328 矩阵取数游戏
* @author d3y1
*/
public class Solution {
private final int MOD = 1000000007;
private final int BASE = 2;
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 相似 -> NC327 取数游戏
* @param matrix int整型ArrayList<ArrayList<>>
* @return int整型
*/
public int matrixScore (ArrayList<ArrayList<Integer>> matrix) {
// return solution1(matrix);
return solution2(matrix);
}
/**
* 动态规划 + 滑动窗口: 越界
*
* dp[t][i][j]表示矩阵第t行剩余列区间[i,j]取数后的最大得分
*
* pow[i]表示第i次取数的权值
* gap表示窗口间隔
*
* j = i+gap
* gap=0时: i=j, 剩余列区间[i,i], 该行仅剩最后1个元素, 当为最后一次(第m次)取数, 权值为pow[m]
* gap>0时: i<j, 剩余列区间[i,j], 该行仅剩最后(gap+1)个元素, 已经取走(m-(gap+1))个元素, 当前为第((m-(gap+1))+1)取数, 即第(m-gap)次取数, 权值为pow[m-gap]
*
* @param matrix
* @return
*/
private int solution1(ArrayList<ArrayList<Integer>> matrix){
int n = matrix.size();
int m = matrix.get(0).size();
long[][][] dp = new long[n+1][m+1][m+1];
long result = 0;
for(int t=1; t<=n; t++){
for(int gap=0; gap<m; gap++){
for(int i=1,j=i+gap; j<=m; i++,j++){
if(i == j){
dp[t][i][j] = ((long)matrix.get(t-1).get(i-1)*(1L<<(m-gap)));
}else{
dp[t][i][j] = (Math.max((long)matrix.get(t-1).get(i-1)*(1L<<(m-gap))+dp[t][i+1][j], (long)matrix.get(t-1).get(j-1) *(1L<<(m-gap))+dp[t][i][j-1]));
}
}
}
result = (result+(dp[t][1][m] % MOD)) % MOD;
}
return (int)result;
}
/**
* 动态规划 + 滑动窗口 + BigInteger
*
* dp[t][i][j]表示矩阵第t行剩余列区间[i,j]取数后的最大得分
*
* pow[i]表示第i次取数的权值
* gap表示窗口间隔
*
* j = i+gap
* gap=0时: i=j, 剩余列区间[i,i], 该行仅剩最后1个元素, 当为最后一次(第m次)取数, 权值为pow[m]
* gap>0时: i<j, 剩余列区间[i,j], 该行仅剩最后(gap+1)个元素, 已经取走(m-(gap+1))个元素, 当前为第((m-(gap+1))+1)取数, 即第(m-gap)次取数, 权值为pow[m-gap]
*
* @param matrix
* @return
*/
private int solution2(ArrayList<ArrayList<Integer>> matrix){
int n = matrix.size();
int m = matrix.get(0).size();
BigInteger[][][] dp = new BigInteger[n+1][m+1][m+1];
// init pow
BigInteger[] pow = new BigInteger[m+1];
pow[0] = new BigInteger("1");
for(int i=1; i<=m; i++){
pow[i] = pow[i-1].multiply(BigInteger.valueOf(BASE));
}
int result = 0;
BigInteger left,right;
// 各行之间互相独立
for(int t=1; t<=n; t++){
// 滑动窗口
for(int gap=0; gap<m; gap++){
for(int i=1,j=i+gap; j<=m; i++,j++){
if(i == j){
dp[t][i][j] = (pow[m-gap].multiply(BigInteger.valueOf(matrix.get(t-1).get(i-1)))) ;
}else{
left = dp[t][i+1][j].add(pow[m-gap].multiply(BigInteger.valueOf(matrix.get(t-1).get(i-1))));
right = dp[t][i][j-1].add(pow[m-gap].multiply(BigInteger.valueOf(matrix.get(t-1).get(j-1))));
if(left.compareTo(right) > 0){
dp[t][i][j] = left;
}else{
dp[t][i][j] = right;
}
}
}
}
result = (result+(dp[t][1][m].mod(BigInteger.valueOf(MOD)).intValue())) % MOD;
}
return result;
}
}