import java.util.*; /** * NC327 取数游戏 * @author d3y1 */ public class Solution { private int result; /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param A int整型ArrayList * @param B int整型ArrayList * @return int整型 */ public int numbergame (ArrayList<Integer> A, ArrayList<Integer> B) { // return solution1(A, B); return solution2(A, B); } /** * dfs: 遍历空间: 超时 * @param A * @param B * @return */ private int solution1(ArrayList<Integer> A, ArrayList<Integer> B){ int n = A.size(); dfs(A, B, 0, n-1, 0, 0, 0); return result; } /** * dfs: 递归 * @param A * @param B * @param left * @param right * @param direction * @param sum * @param index */ private void dfs(ArrayList<Integer> A, ArrayList<Integer> B, int left, int right, int direction, int sum, int index){ if(direction == 1){ sum += A.get(left) * B.get(index); left++; index++; if(left > right){ result = Math.max(result, sum); return; } } if(direction == -1){ sum += A.get(right) * B.get(index); right--; index++; if(left > right){ result = Math.max(result, sum); return; } } dfs(A, B, left, right, 1, sum, index); dfs(A, B, left, right, -1, sum, index); } /** * 动态规划 * * dp[i][j]表示区间[i,j]可以取得的最大价值 * * len表示区间[i,j]长度, 亦即剩余取数次数(总共n次) * len = j-i+1 * * n-len表示下次取数时对应的价值索引(0到n-1, 递增) * * { A.get(i)*B.get(n-len) , i=j * dp[i][j] = { * { Math.max(dp[i+1][j]+A.get(i)*B.get(n-len), dp[i][j-1]+A.get(j)*B.get(n-len)) , i<j * * @param A * @param B * @return */ private int solution2(ArrayList<Integer> A, ArrayList<Integer> B){ int n = A.size(); int[][] dp = new int[n][n]; int len; // 左边界i 降序 for(int i=n-1; i>=0; i--){ // 右边界j 升序 for(int j=i; j<n; j++){ len = j-i+1; if(i == j){ dp[i][j] = A.get(i)*B.get(n-len); }else{ // dp[i+1][j]+A.get(i)*B.get(n-len) 左边界i依赖于后面i+1(i<-i+1) 所以i应降序 // dp[i][j-1]+A.get(j)*B.get(n-len) 右边界j依赖于前面j-1(j-1->j) 所以j应升序 dp[i][j] = Math.max(dp[i+1][j]+A.get(i)*B.get(n-len), dp[i][j-1]+A.get(j)*B.get(n-len)); } } } return dp[0][n-1]; } }