确定ABCDE五个学校名次

题目描述:

A、B、C、D、E五个学校,A说E是第一,B说B是第二,C说A是最差的,D说C不是最好的,E说D是最好的。只有第一和第二名说的是对的,其他说的都是错的,请编程确定五个学校的名次。

解题思路:

第一想法就是递归,分别5个坑,然后递归循环填充,通过一个判断方法去判断是否能填充。

package com.miaomiao.toutiao;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class SchoolTest {

   static Map<Character,Pair<Character,int[]>> map =new HashMap<>();

    public static Character nomals[] = new Character[5];

    public SchoolTest() {
        map.put('A',new Pair<>('E', new int[]{1}));
        map.put('B',new Pair<>('B', new int[]{2}));
        map.put('C',new Pair<>('A', new int[]{5}));
        map.put('D',new Pair<>('C', new int[]{2,3,4,5}));
        map.put('E',new Pair<>('D', new int[]{1}));
    }

    public static void main(String[] args) {
        new SchoolTest();
        for (int i = 1; i <=map.size() ; i++) {
            nomals[0] = (char)('A'+i-1);
            digui(1);
        }
    }

    public static void digui( int one){
        if(nomals[0]!=null && nomals[1]!=null && one!=1){
            //由于进到这里的方法都是,排位第三到五的顺位,所以认为都是虚假言论
            for (int j = 1; j <=map.size() ; j++) {
                char num = (char)('A'+j-1);
                boolean flag = true;
                //这里的作用,就是判断数组里是否已经有这个字母了。k<=one:只判断已经填充的字母
                for (int k = 1; k <=map.size() ; k++){
                    if(k<=one && nomals[k-1]!=null && nomals[k-1]==num ){
                        flag = false;
                        break;
                    }
                }
                if(!flag){
                    continue;
                }

                if(judge(one+1,num)){
                    nomals[one] = num;
                    if(one==4){
                        System.out.println(Arrays.toString(nomals));
                    }else{
                        digui(one+1);
                    }
                }
            }
        }else{
            for (int j = 1; j <=map.size() ; j++) {
                if(j==(nomals[0]-64)){
                    continue;
                }
                nomals[1] = (char)('A'+j-1);
                if(judge(one+1,nomals[1])){
                    digui(one+1);
                }
            }
        }
    }

    /**
     *
     * @param round 第几轮
     * @param num 哪个字母
     * @return
     */
    public static boolean judge(int round,char num){
        //代表说的是真的

        Pair<Character,int[]> one = map.get(nomals[0]);
        Pair<Character,int[]> two = map.get(nomals[1]);

        //第一名所说的,和传入的这个字母自己所在的排名不符合
        if(one.getN() == num && Arrays.binarySearch(one.getS(), round)<0 ){
            return false;
            //第二名所说的,和传入的这个字母自己所在的排名不符合
        }else if(two.getN() == num && Arrays.binarySearch(two.getS(), round)<0 ){
            return false;
        }
        //判断第一名是否为真
        if(one.getN() == nomals[0] && Arrays.binarySearch(one.getS(), 1)<0){
            return false;
        }
        if(two.getN() == nomals[0] && Arrays.binarySearch(two.getS(), 1)<0){
            return false;
        }


        //以上都是说真话的判断,现在是说假话的判断
        for(Map.Entry<Character,Pair<Character,int[]>> entry : map.entrySet()){
            Pair<Character,int[]> fake = entry.getValue();
            if(fake == one || fake==two){
                continue;
            }else{
                //先判断,第一第二名的真伪
                if(fake.getN() == nomals[0] && Arrays.binarySearch(one.getS(), 1)>=0 ){
                    return false;
                }else if(fake.getN() == nomals[1] && Arrays.binarySearch(one.getS(), 2)>=0 ){
                    return false;
                    //再判断 传入的这个字母自己所在的排名,和这个说谎话的人所说的是否一致,一致就说明是不正确的排名
                }else if(fake.getN() == num && Arrays.binarySearch(fake.getS(), round)>=0 ){
                    return false;
                }
            }
        }
        return true;


    }
}

class Pair<N,S>{
    private N n;
    private S s;

    public Pair(N n, S s) {
        this.n = n;
        this.s = s;
    }

    public N getN() {
        return n;
    }

    public void setN(N n) {
        this.n = n;
    }

    public S getS() {
        return s;
    }

    public void setS(S s) {
        this.s = s;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值