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; } }