整型数组array,代表数值不同的纸牌排成一条线,玩家a和b依次拿走每张,规定a先拿,b后拿;每次只能拿最左或最右的,返回胜者的分数

问题描述:

整型数组array,代表数值不同的纸牌排成一条线,玩家a和b依次拿走每张,规定a先拿,b后拿;每次只能拿最左或最右的,a和b都很聪明,请返回胜者的分数。

举例数组:arr = { 8, 6, 7, 9 };

要求返回最大值。

解决方案:此处我们采用三种方案进行,基本思路是从暴力递归到动态规划的演变。

1、暴力递归:核心代码如下


public class NanDaoCardsInLine {
    public static void main(String[] args) {
        int[] arr = { 8, 6, 7, 9 };
        System.out.println(success1(arr));
       
    }


    /**
     * 暴力递归方案
     * @param arr
     * @return
     */
    private static int success1(int[] arr) {
        if(arr == null || arr.length == 0){
            return 0;
        }
        int first = f1(arr,0,arr.length - 1);//a先取数据的
        int second = s1(arr,0,arr.length - 1);//b后取数据
        return Math.max(first,second);//返回最大的分数
    }

    private static int s1(int[] arr, int L, int R) {
        if(L == R){
            return 0;//相等时肯定被a取走
        }
        int sum1 = f1(arr,L + 1,R);//a取了L位置的数
        int sum2 = f1(arr,L,R - 1);//a取了R位置的数
        return Math.min(sum1,sum2);//返回最小的分数
    }

    private static int f1(int[] arr, int L, int R) {
        if(L == R){
            return arr[L];//相等时肯定被a取走
        }
        int sum1 = arr[L] + s1(arr,L + 1,R);//a取了L位置的数,然后变成了后取数据的角色
        int sum2 = arr[R] + s1(arr,L,R - 1);//a取了R位置的数,然后变成了后取数据的角色
        return Math.max(sum1,sum2);//返回最大的分数
    }

}

2、加缓存方案:

2.1、分析重复现象的图示:

 有重复现象就可以加缓存过滤重复值。

2.2、核心代码如下:


public class NanDaoCardsInLine {
    public static void main(String[] args) {
        int[] arr = { 8, 6, 7, 9 };
      
        System.out.println(success2(arr));
       
    }
 
    /**
     * 杀缓存方案
     * @param arr
     * @return
     */
    private static int success2(int[] arr) {
        if(arr == null || arr.length == 0){
            return 0;
        }
        int N = arr.length;
        int[][] fCache = new int[N][N];//a的缓存
        int[][] sCache = new int[N][N];//b的缓存
        //赋默认值
        for(int i = 0;i < N;i++){
            for(int j = 0;j < N;j++){
                fCache[i][j] = -1;
                sCache[i][j] = -1;
            }
        }
        int sum1 = f2(arr,0,N - 1,fCache,sCache);
        int sum2 = s2(arr,0,N - 1,fCache,sCache);
        return Math.max(sum1,sum2);
    }

    private static int s2(int[] arr, int L, int R, int[][] fCache, int[][] sCache) {
        //如果已经赋值即缓存中有数据,就直接返回
        if(sCache[L][R] != -1){
            return sCache[L][R];
        }
        int res = 0;
        if(L != R){
            int sum1= f2(arr,L + 1,R,fCache,sCache);
            int sum2= f2(arr,L,R - 1,fCache,sCache);
            res = Math.min(sum1,sum2);
        }
        sCache[L][R] = res;//缓存中赋值
        return res;
    }

    private static int f2(int[] arr, int L, int R, int[][] fCache, int[][] sCache) {
        //如果已经赋值即缓存中有数据,就直接返回
        if(fCache[L][R] != -1){
            return fCache[L][R];
        }
        int res = 0;
        if(L == R){
            res = arr[L];
        }else {
            int sum1 = arr[L] + s2(arr,L + 1,R,fCache,sCache);
            int sum2 = arr[R] + s2(arr,L,R - 1,fCache,sCache);
            res = Math.max(sum1,sum2);
        }
        fCache[L][R] = res;//缓存中赋值
        return res;
    }

}

3、标准动态规划:

3.1、先取即a的二维数组

 L > R 的不合逻辑的地方用 * 号标记。 

3.1、后取即b的二维数组

 L > R 的不合逻辑的地方用 * 号标记。  

3.3、核心代码如下:


public class NanDaoCardsInLine {
    public static void main(String[] args) {
        int[] arr = { 8, 6, 7, 9 };
     
        System.out.println(success3(arr));
    }

    /**
     * 动态规划方案
     * @param arr
     * @return
     */
    private static int success3(int[] arr) {
        if(arr == null || arr.length == 0){
            return 0;
        }
        int N = arr.length;
        int[][] f3 = new int[N][N];//a的缓存
        int[][] s3 = new int[N][N];//b的缓存
        //a的对角线赋默认值,b中对角线是0
        for(int i = 0;i < N;i++){
            f3[i][i] = arr[i];
        }
        for(int start = 1;start < N;start++){
            int L = 0;
            int R = start;
            while (R < N){//防止数组越界
                f3[L][R] = Math.max(arr[L] + s3[L + 1][R],arr[R] + s3[L][R - 1]);//a二维数组中赋值
                s3[L][R] = Math.min(f3[L + 1][R],f3[L][R - 1]);//b二维数组中赋值
                L++;
                R++;
            }
        }
        return Math.max(f3[0][N - 1],s3[0][N - 1]);
    }
 

}

4、三种方案执行结果:

到此,三种方案分享完毕,大家一定要多思考,勤练习,定会进步很快!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寅灯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值