长跑排名预测
参考代码
1 public class yucepaiming { 2 //存储运动员数量与围观党数量 3 private static int n,m; 4 //存储围观党预测结果 5 private static String[][] s; 6 //存储运动员排名顺序 7 private static int[] list; 8 //存储满足预测的结果总和 9 private static int sum; 10 private static List<int[]> alist = new ArrayList<>(); 11 public static void main(String[] args) { 12 String str = new Scanner(System.in).nextLine(); 13 n = Integer.parseInt(str.split(" ")[0]); 14 m = Integer.parseInt(str.split(" ")[1]); 15 s = new String [m][]; 16 for(int i=0;i<m;i++){ 17 str = new Scanner(System.in).nextLine(); 18 s[i]=str.split(" "); 19 } 20 //初始化排名,1号第一名,2号第二名... 21 list = new int[n]; 22 for(int i=0;i<n;i++){ 23 list[i]=i; 24 } 25 //使用回溯算法,参数为运动员排名,0为第一名 26 dg(0); 27 System.out.println(sum); 28 for(int[] a : alist){ 29 str = Arrays.toString(a); 30 str = str.replace("[", ""); 31 str = str.replace("]", ""); 32 System.out.println(str); 33 } 34 } 35 private static void dg(int index) { 36 //当最后一个顺序已经排好并且满足预测条件的话 37 if(index == n && filter(list)){ 38 sum++; 39 //注意必须重新复制数组,因为存入集合中的只是数组地址。如果没有复制,当数组改变时,集合的元素也会改变 40 alist.add(Arrays.copyOf(list, list.length)); 41 }else{ 42 /*交换顺序->排下一个运动员->还原顺序,注意当前交换顺序的运动员只能交换他后面的运动员的顺序, 43 这样交换的两个运动员在递归过程中才不会重复交换,产生错误的数据,所以i=index,而不是0 */ 44 for(int i=index;i<n;i++){ 45 //交换顺序 46 int t = list[i]; 47 list[i] = list[index]; 48 list[index] = t; 49 //排下一个运动员 50 dg(index+1); 51 //还原顺序 52 t = list[i]; 53 list[i] = list[index]; 54 list[index] = t; 55 } 56 } 57 } 58 private static boolean filter(int[] data) { 59 boolean falg = true; 60 for(int i=0;i<m;i++){ 61 //这个预测是错误的 62 if(s[i][s[i].length-1].equals("0")){ 63 //当所以运动员都满足预测则预测错误 64 for(int j=0,k=1;j<n;j++){ 65 if(Integer.parseInt(s[i][k])==list[j]&&++k==s[i].length-1){ 66 falg = false; 67 } 68 } 69 }else{//这个预测是正确的 70 falg = false; 71 //当所以运动员都满足预测则预测正确 72 for(int j=0,k=1;j<n;j++){ 73 //原理同错误预测 74 if(Integer.parseInt(s[i][k])==list[j]&&++k==s[i].length-1){ 75 falg = true; 76 } 77 } 78 } 79 } 80 return falg; 81 } 82 }
运行结果
注意:
1 for(int j=0,k=1;j<n;j++){ 2 if(Integer.parseInt(s[i][k])==list[j]&&++k==s[i].length-1){ 3 falg = false; 4 } 5 }
这段代码意思是当所以运动员都满足预测则预测错误
别看这个if语句只有一行,逻辑还是特别复杂的
首先要明白&&,当左边不满足,右边就不会执行了
当第一次执行Integer.parseInt(s[i][k])==list[j]满足条件时,会把第i个围观党预测的第一个人从已经排好的数组list中找出来
这时k为围观党预测的人在s[i][]中的下标,j为list数组中的下标,他们指的同一个运动员
当第一个条件满足会执行++k==s[i].length-1,这句话的意思是如果++k超过了存预测部分的长度,换句话说就是当前k下标是最后一个预测
因为s数组最后还存了一个状态,这句话的对错与否,所以s[i].length-1
所以这个循环加上if判断的运行过程就是:
在排名中找到第一个预测,判断这个预测是不是最后一个预测(当预测只有一个人会判断为预测错误,当然这样的预测是无意义的),
如果是则判断为预测错误,否则判断下一个预测(k++),然后找到运动员排名位置(Integer.parseInt(s[i][k])==list[j]),
注意循环是j++,也就是找到的运动员必须在上一个运动员后面的,这样才能满足预测
如果找不到k则在循环结束都不可能满足++k==s[i].length-1,则说明预测正确,否则判断当前是否为最后一个,若是,则说明所有预测都成立,
则返回预测错误,若不是最后一个,则判断下一个预测