[NOIP2011普及组]瑞士轮 JAVA实现

题目描述

2*N名编号为1~2N的选手共进行R轮比赛。每轮比赛开始前,以及所有比赛结束后,都会按照总分从高到低对选手进行一次排名。选手的总分为第一轮开始前的初始分数加上已参加过的所有比赛的得分和。总分相同的,约定编号较小的选手排名靠前。

每轮比赛的对阵安排与该轮比赛开始前的排名有关:第1名和第2名、第3名和第4名、……、第2K-1名和第2K名、……、第2N-1名和第2N名,各进行 一场比赛。每场比赛胜者得 1分,负者得0分。也就是说除了首轮以外,其它轮比赛的安排均不能事先确定,而是要取决于选手在之前比赛中的表现。

现给定每个选手的初始分数及其实力值,试计算在R轮比赛过后,排名第Q的选手编号是多少。我们假设选手的实力值两两不同,且每场比赛中实力值较高的总能获胜。

输入格式

输入的第一行是三个正整数N、R、Q,每两个数之间用一个空格隔开,表示有2*N名选手、R轮比赛,以及我们关心的名次Q。

第二行是2*N个非负整数s1,s2,…,s2N,每两个数之间用一个空格隔开,其中si表示编号为i的选手的初始分数。

第三行是2*N个正整数w1,w2,…,w2N,每两个数之间用一个空格隔开,其中wi表示编号为i的选手的实力值。

输出格式

输出只有一行,包含一个整数,即R轮比赛结束后,排名第Q的选手的编号。

样例输入

2 4 2
7 6 6 7
10 5 20 15

样例输出

1

两种java代码解决

1、每轮比赛得出新的积分后通过冒泡排序或快速排序得出新的排名(一维数组存储选手信息)

  1 package xpc.sort;
  2 
  3 import java.util.Scanner;
  4 
  5 /**
  6  * 瑞士轮问题实现
  7  * 
  8  * @author xpc
  9  *
 10  */
 11 public class RuiShiLun {
 12     
 13     public static void main(String[] args) {
 14         RuiShiLun obj = new RuiShiLun();
 15         int no[];//每个选手的编号,顺序按名次
 16         int s[];
 17         int w[];
 18         Scanner scanner = new Scanner(System.in);
 19         System.out.println("请输入N R Q");
 20         String  str = scanner.nextLine();
 21         String [] temp = str.split(" ");
 22         int n = Integer.parseInt(temp[0]);
 23         int r = Integer.parseInt(temp[1]);
 24         int q = Integer.parseInt(temp[2]);
 25         no = new int[2*n];
 26         s = new int[2*n];
 27         w = new int[2*n];
 28         System.out.println("请输入对应编号选手初始分数:");
 29         str = scanner.nextLine();
 30         temp = str.split(" ");
 31         for(int i = 0; i < temp.length;i++){
 32             s[i] = Integer.parseInt(temp[i]);
 33             no[i] = i+1;
 34         }
 35         System.out.println("请输入对应编号选手实力值:");
 36         str = scanner.nextLine();
 37         temp = str.split(" ");
 38         for(int i = 0; i < w.length;i++){
 39             w[i] = Integer.parseInt(temp[i]);
 40         }
 41 //        int no[] = new int[]{1,2,3,4};//每个选手的编号,顺序按名次
 42 //        int s[] = new int[]{7,6,6,7};
 43 //        int w[] = new int[]{10,5,20,15};
 44 //        int n = 2;
 45 //        int r = 4;
 46 //        int q = 2;
 47         int i = 0;
 48         while(i < r){
 49             i++;
 50             System.out.println("第"+i+"轮比赛后:");
 51             obj.sigleAfter(no,s,w);
 52             for(int t = 0 ; t < s.length;t++){
 53                 System.out.println("第"+(t+1)+"名:"+no[t]+",分数:"+s[t]);
 54             }
 55         }
 56         System.out.println("第"+r+"轮后排名第"+q+"的编号是:"+no[q-1]);
 57     }
 58     
 59     public  void sigleAfter(int no[],int s[],int w[]){
 60         for(int i = 0; i < s.length-1; i+=2){
 61             if(w[i] > w[i+1]){
 62                 s[i] ++;
 63             }else{
 64                 s[i+1]++;
 65             }
 66         }
 67         //选择排序
 68 //        chosesort(s, no, w);
 69         //快排
 70         quicksort(s,no,w,0,s.length-1);
 71     }
 72     
 73     public void chosesort(int s[],int []no,int w[]){
 74         for(int i = 0; i < s.length-1; i++){
 75             for(int j = i+1; j< s.length;j++){
 76                 if(s[i] < s[j]){
 77                     int temp = s[i];
 78                     s[i] = s[j];
 79                     s[j] = temp;
 80                     
 81                     temp = no[i];
 82                     no[i] = no[j];
 83                     no[j] = temp;
 84                     
 85                     temp = w[i];
 86                     w[i] = w[j];
 87                     w[j] = temp;
 88                 }else if(s[i] == s[j]){
 89                     if(no[i] > no[j]){
 90                         int temp = s[i];
 91                         s[i] = s[j];
 92                         s[j] = temp;
 93                         
 94                         temp = no[i];
 95                         no[i] = no[j];
 96                         no[j] = temp;
 97                         
 98                         temp = w[i];
 99                         w[i] = w[j];
100                         w[j] = temp;
101                     }
102                 }
103             }
104         }
105     }
106     
107     /**
108      * 三分取中值策略
109      * @param left
110      * @param right
111      * @return
112      */
113     public int median3(int s[],int []no,int w[],int left,int right){
114         int center = (left+right)/2;
115         if(s[left] < s[center]){
116             swapReference(no,s,w, center, left);
117         }
118         if(s[center] < s[right]){
119             swapReference(no,s,w, right, center);
120         }
121         if(s[left] < s[center]){
122             swapReference(no,s,w, left, center);
123         }
124         if(left+1 > right){
125             swapReference(no,s,w, center, right);
126         }
127         return s[right];
128     }
129     
130     public void quicksort(int []s,int no[],int w[],int left,int right){
131         if(left < right){
132             int pivot = median3(s,no,w,left,right);
133             if(right - left > 1){
134                 int i = left;
135                 int j = right;
136                 while(true){//大的放左边,小的放右边
137                     while(s[++i] > pivot){
138                         if(s[i] == pivot && no[i] >= no[right]){//积分相同,i的编号较大所以需要移到右边
139                             break;
140                         }
141                     }
142                     while(s[--j] <= pivot){
143                         if(s[j] == pivot && no[j] <= no[right]){//积分相同,i的编号较小所以需要移到左边
144                             break;
145                         }
146                     }
147                     if(i < j){
148                         swapReference(s,no,w, i, j);
149                     }else{
150                         break;
151                     }
152                 }
153                 swapReference(s,no,w, i, right);
154                 quicksort(s,no,w, left,i-1);
155                 quicksort(s,no,w, i+1, right);
156             }
157             
158         }
159     }
160     
161     /**
162      * 互换数组中的元素
163      * @param a
164      * @param i
165      * @param j
166      */
167     private void swapReference(int []no ,int []s,int w[],int i,int j){
168         int temp = no[i];
169         no[i] = no[j];
170         no[j] = temp;
171         
172         temp = s[i];
173         s[i] = s[j];
174         s[j] = temp;
175         
176         temp = w[i];
177         w[i] = w[j];
178         w[j] = temp;
179     }
180 
181 }

2、除第一次排序通过快速排序将积分重排,后面每轮将选手分为胜者组合败者组两组,通过归并合在一起(二维数组存储选手信息)

package xpc.sort;

public class RuiShiLun2 {
    
    public static void main(String[] args) {
        RuiShiLun2 sort = new RuiShiLun2();
        int n = 2;
        int r = 4;
        int q = 2;
//        int no[] = new int[]{1,2,3,4};//每个选手的编号,顺序按名次
//        int s[] = new int[]{7,6,6,7};
//        int w[] = new int[]{10,5,20,15};
        int ans [][] = new int[2*n][3];//0:积分  1:实力 2:编号
        ans[0][0] = 7;
        ans[0][1] = 10;
        ans[0][2] = 1;
        
        ans[1][0] = 6;
        ans[1][1] = 5;
        ans[1][2] = 2;
        
        ans[2][0] = 6;
        ans[2][1] = 20;
        ans[2][2] = 3;
        
        ans[3][0] = 7;
        ans[3][1] = 15;
        ans[3][2] = 4;
        int a[][] = new int [n][3];//胜者组
        int b[][] = new int [n][3];//败者组
        
        sort.sigleAfter(a, b, ans);
        
        int r1 = 1;
        sort.chosesort(ans);
        System.out.println("第"+r1+"轮后排名");
        for(int i = 0 ; i < ans.length;i++){
            System.out.println("第"+(i+1)+"名:"+ans[i][2]+"-"+ans[i][0]+"-"+ans[i][1]);
        }
        while(r > 1 && r1 <r){
            r1++;
            sort.sigleAfter(a, b, ans);
            sort.mergeArray(a, b, ans);
            System.out.println("第"+r1+"轮后排名");
            for(int i = 0 ; i < ans.length;i++){
                System.out.println("第"+(i+1)+"名:"+ans[i][2]+"-"+ans[i][0]+"-"+ans[i][1]);
            }
        }
        System.out.println("第"+r+"轮后排名第"+q+"的编号是:"+ans[q-1][2]);
    }
    private void sigleAfter(int a[][],int b[][],int ans[][]){
        int j = 0;
        for(int i = 0; i < ans.length-1; i+=2){
            if(ans[i][1] > ans[i+1][1]){
                ans[i][0]++;
                a[j] = ans[i];
                b[j] = ans[i+1];
            }else{
                ans[i+1][0]++;
                a[j] = ans[i+1];
                b[j] = ans[i];
            }
            j++;
        }
    }
    
    /**
     * 
     * 选择排序
     * @param s
     * @param no
     * @param w
     */
    public void chosesort(int ans[][]){
        for(int i = 0; i < ans.length-1; i++){
            for(int j = i+1; j< ans.length;j++){
                if(ans[i][0] < ans[j][0]){
                    int[] temp = ans[i];
                    ans[i] = ans[j];
                    ans[j] = temp;
                    
                }else if(ans[i][0] == ans[j][0]){
                    if(ans[i][2] > ans[j][2]){
                        int []temp = ans[i];
                        ans[i] = ans[j];
                        ans[j] = temp;
                    }
                }
            }
        }
    }
    
    /**
     * 胜者组败者组做归并
     * @param a
     * @param b
     * @param ans
     */
    private void mergeArray(int a[][],int b[][],int ans[][]){
        int k = 0;
        int t = 0;
        int m = 0;
        while(t<a.length && m<b.length){
            if(a[t][0] > b[m][0]){
                ans[k++] = a[t++];
            }else{
                if(a[t][0] == b[m][0] && a[t][2] < b[m][2]){
                    //积分相同编号小的往前排
                    ans[k++] = a[t++];
                    continue;
                }
                ans[k++] = b[m++];
            }
        }
        while(t<a.length){
            ans[k++] = a[t++];
        }
        while(m<b.length){
            ans[k++] = b[m++];
        }
    }
}
View Code

 

posted @ 2016-01-22 14:57  OneNewbie  阅读(468)  评论(0)    收藏  举报