1. 程式人生 > >洛谷P1080 國王遊戲【大數】【貪心】

洛谷P1080 國王遊戲【大數】【貪心】

compare 簡單 .org ner next ref rgs integer 選擇

題目:https://www.luogu.org/problemnew/show/P1080

題意:

一個國王和n個大臣,每個人左右手上都有一個數值。

現在將國王排在隊首,將大臣進行排序。每個大臣的值是他前面所有人的左手值的積除以他自己右手的值。

問怎樣的排序可以使得大臣的值中的最大值盡可能的小。

思路:

看題目感覺會是一個排序的問題,但是剛開始沒想出來拿什麽當關鍵字。

後來看了題解。感覺這種題目的關鍵是先考慮只有兩個對象,分別計算這兩個對象一前一後得到的答案,然後根據答案的不等式推出應該以什麽作為關鍵字比較兩個對象。

因此我們考慮一個大臣左右手的數值是a1,b1,另一個大臣走右手數值是a2,b2,國王的左右手數值是a0,b0

當1在前2在後時,可以得到$k1=a0/b1$和$k2=a0*a1/b2$,設此時答案是ans1

當2在前1在後時,可以得到$k3=a0/b2$和$k4=a0*a2/b1$,設此時答案是ans2

可以發現$k3<k2,k4>k1$

如果$ans1<ans2$恒成立也就是說我們要選擇1在前2在後的情況,即$max(k1,k2)<max(k3,k4)$,那麽$k4>k2$且$k4>k3$,此時$a2*b2>a1*b1$

這說明了左右手之積較小的應該放在前面。

推出了排序的規則,接下來就比較簡單了。要註意的是這道題用到了大數。

 1 import java.lang.reflect.Array;
2 import java.math.BigInteger; 3 import java.util.Arrays; 4 import java.util.BitSet; 5 import java.util.Comparator; 6 import java.util.Scanner; 7 8 public class Main { 9 private static class node{ 10 int lft; 11 int rgt; 12 } 13 final static int maxn = 1005
; 14 static node[] peo; 15 static Scanner scan = new Scanner(System.in); 16 static int n; 17 18 private static class cmp implements Comparator<node> { 19 @Override 20 public int compare(node a, node b){ 21 if(a.lft * a.rgt < b.lft * b.rgt)return -1; 22 else if(a.lft * a.rgt == b.lft * b.rgt)return 0; 23 else return 1; 24 } 25 } 26 public static void main(String[] args){ 27 n = scan.nextInt(); 28 peo = new node[n + 1]; 29 peo[0] = new node(); 30 peo[0].lft = scan.nextInt(); 31 peo[0].rgt = scan.nextInt(); 32 for(int i = 1; i <= n; i++){ 33 peo[i] = new node(); 34 peo[i].lft = scan.nextInt(); 35 peo[i].rgt = scan.nextInt(); 36 } 37 Arrays.sort(peo, 1, n + 1, new cmp()); 38 39 BigInteger res = BigInteger.valueOf(peo[0].lft); 40 BigInteger ans = BigInteger.ZERO; 41 for(int i = 1; i <= n; i++){ 42 ans = ans.max(res.divide(BigInteger.valueOf(peo[i].rgt))); 43 res = res.multiply(BigInteger.valueOf(peo[i].lft)); 44 } 45 46 System.out.println(ans); 47 } 48 }

洛谷P1080 國王遊戲【大數】【貪心】