演算法學習——貪心演算法之取數遊戲(顯示兩端數字)
阿新 • • 發佈:2018-12-17
演算法描述
取數遊戲:A與B玩取數遊戲,隨機產生的2n個整數排成一列,只顯示兩端的整數,只有當A或B取完數會顯示下一個數或者是前一個數(若是取末尾的數)
A的取數策略:採用貪心策略,每次取數取兩個數中最大的那個數
B的取數策略:當兩個數相差較大,取大的那個數,若相差為1,則在這兩個數中隨意取一個數
模擬A與B的取數過程
演算法思路
隨機產生數值,我們使用Java中的Math.random()方法即可
為了方便取數,將隨機產生的2n個整數放在連結串列中,連結串列中有方法可以取出第一個數和最後一個數
getFirst()
返回第一個元素的數值,不將該元素移出連結串列removeFirst()
getLast()
返回最後一個元素的數值,不將該元素移出連結串列removeLast()
將最後一個元素移出連結串列,返回該元素的數值設定一個布林變數
flag
,flag=true
輪到A取數flag=false
輪到B取數分別用兩個一維陣列存放A與B的取數
A取數採用貪心策略,我們使用get方法,獲得一個數和最後一個數,取大數存放在A陣列中
B取數有兩個選擇,相差較大(也就是相差大於1),我們就取大數(這裡我們在實際當中需要採用
絕對值
);若是等於1,則隨意取,
我們可以使用隨機數的方法,若是隨機數大於0.5,則取第一個數,否則取末尾那個數
如果是A先取數的話,B到最後會出現只剩下一個數的情況,這個時候B沒有選擇,只能取這個數
判斷輸贏的話,只需要比較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獲勝了"); }