1. 程式人生 > >演算法學習——貪心演算法之取數遊戲(顯示兩端數字)

演算法學習——貪心演算法之取數遊戲(顯示兩端數字)

演算法描述

取數遊戲:A與B玩取數遊戲,隨機產生的2n個整數排成一列,只顯示兩端的整數,只有當A或B取完數會顯示下一個數或者是前一個數(若是取末尾的數)

A的取數策略:採用貪心策略,每次取數取兩個數中最大的那個數

B的取數策略:當兩個數相差較大,取大的那個數,若相差為1,則在這兩個數中隨意取一個數

模擬A與B的取數過程

演算法思路

  1. 隨機產生數值,我們使用Java中的Math.random()方法即可

  2. 為了方便取數,將隨機產生的2n個整數放在連結串列中,連結串列中有方法可以取出第一個數和最後一個數

    getFirst()返回第一個元素的數值,不將該元素移出連結串列

    removeFirst()

    將第一個元素連結串列連結串列,返回該元素的數值

    getLast()返回最後一個元素的數值,不將該元素移出連結串列

    removeLast()將最後一個元素移出連結串列,返回該元素的數值

  3. 設定一個布林變數flag,flag=true輪到A取數flag=false輪到B取數

  4. 分別用兩個一維陣列存放A與B的取數

  5. A取數採用貪心策略,我們使用get方法,獲得一個數和最後一個數,取大數存放在A陣列中

  6. B取數有兩個選擇,相差較大(也就是相差大於1),我們就取大數(這裡我們在實際當中需要採用絕對值);

    若是等於1,則隨意取,我們可以使用隨機數的方法,若是隨機數大於0.5,則取第一個數,否則取末尾那個數

    如果是A先取數的話,B到最後會出現只剩下一個數的情況,這個時候B沒有選擇,只能取這個數

  7. 判斷輸贏的話,只需要比較A陣列的總和與B陣列的總和即可判斷出輸贏

演算法實現

    Scanner scaner = new Scanner(System.in);
    int n = scaner.nextInt();
    scaner.close();
    LinkedList<Integer> list = new LinkedList<Integer>();
    int[] A = new int[n];//存放A所取的數值
    int[] B = new int[n];//存放B所取的數值
    
    for(int i=0;i<2*n;i++){
        int temp=(int)(Math.random() * 100) ;//0到100的隨機數
        list.add(temp);//存入連結串列中
    }
    
    boolean flag = true;//A先取數
    int count = 0;
    //當B陣列的最後一個不為0的時候(即是B拿到了最後一個數的時候),退出while
    while(count<n){
        if(flag){
            
            if(list.getFirst()>list.getLast()){
                A[count] = list.removeFirst();
            }else{
                A[count]=list.removeLast();
            }
            System.out.println("A取"+A[count]); 
            flag=false; //改變flag,輪到B取數
        }else{
            
            if(list.getFirst()==list.getLast()){//當還剩下一個數的時候,B只能取當前那個數
                B[count]=list.removeFirst();
            }else if(list.getFirst()-list.getLast()>1){
                B[count] = list.removeFirst();//選擇最大的那個數
            }else if(Math.abs(list.getFirst()-list.getLast())==1){
                //B隨機選擇
                if(Math.random()>0.5){
                    B[count]=list.removeLast();
                }else{
                    B[count]=list.removeFirst();
                }
            }else{
                B[count]=list.removeLast();//第一個數比末尾的數要小,因為上述條件已經排除了等於1的情況,所以末尾的數一定是與第一個數相差較大
            }
            System.out.println("B取"+B[count]);
            count++;
            flag = true;//輪到A取數
        }
    }
    
    int a=A[0],b=B[0];  
    //判斷輸贏
    for(int i=1;i<A.length;i++){
        a = a+A[i];
        b = b+B[i];
    }
    
    if(a>b){
        System.out.println("A獲勝了");
    }else{
        System.out.println("B獲勝了");
    }

結果