请教大家一个java习题的思路,感觉好复杂的样子

qq_29448025 2021-04-14 09:16:41
java书上选择结构章节后,有一个课后习题,题目描述是下面这样的:



这个选择结构是算不出来的吧。如果有别的思路,如循环和数组,大家也请指出,能解出来也行。
...全文
1043 19 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaoxiangqing 2021-04-20
  • 打赏
  • 举报
回复
android_cai_niao 2021-04-20
  • 打赏
  • 举报
回复
最后,送上一个Java版的暴力破解实现,方便大家了解一下!习惯了Kotlin,写Java实在是太痛苦了,大家可以对比一下前面的代码,一模一样的实现,java明显需要比较多的代码,java实现如下:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Test {

    public static class Answer {
        public int number;
        public String name;

        public Answer(int number, String name) {
            this.number = number;
            this.name = name;
        }

        @Override
        public String toString() {
            return number + name;
        }
    }

    public static void main(String[] args) {
        Answer[][] allAnswers = {
                {new Answer(2, "陕西"), new Answer(5, "甘肃")},
                {new Answer(2, "湖北"), new Answer(4, "山东")},
                {new Answer(1, "山东"), new Answer(5, "吉林")},
                {new Answer(3, "湖北"), new Answer(4, "吉林")},
                {new Answer(2, "甘肃"), new Answer(3, "陕西")}
        };
        Answer[][] answerSheet = getAnswerSheet(allAnswers);
        List<Answer[]> rightAnswer = findRightAnswers(answerSheet);
        rightAnswer.forEach(answers -> System.out.println(Arrays.toString(answers)));
    }

    public static Answer[][] getAnswerSheet(Answer[][] allAnswers) {
        // 计算答案表的大小为:2的allAnswers.size次幂
        int sheetSize = (int) Math.pow(2, allAnswers.length);
        // 创建答案表
        Answer[][] answerSheet = new Answer[sheetSize][allAnswers.length];
        // 遍历所有答案,并填充到答案表中
        for (int outIndex = 0; outIndex < allAnswers.length; outIndex++) {
            // 计算答案可以连续填充的最大次数
            int maxPutCount = (int) Math.pow(2, allAnswers.length - 1 - outIndex);
            Answer[] answers = allAnswers[outIndex];
            for (int index = 0; index < answers.length; index++) {
                Answer answer = answers[index];
                int putCount = 0;
                for (int i = 0; i < answerSheet.length; i++) {
                    if (++putCount <= maxPutCount) {
                        answerSheet[i + index * maxPutCount][outIndex] = answer;
                    } else if (putCount % maxPutCount == 0) {
                        putCount = 0;
                    }
                }
            }
        }
        return answerSheet;
    }

    /** 找到答案表中的所有正确答案 */
    public static List<Answer[]> findRightAnswers(Answer[][] answerSheet) {
        List<Answer[]> rightAnswer = new ArrayList<>();
        // 遍历每一组答案,并验证是否正确
        for (Answer[] oneGroupAnswer : answerSheet) {
            if (isRightAnswer(oneGroupAnswer)) {
                rightAnswer.add(oneGroupAnswer);
            }
        }
        return rightAnswer;
    }

    /** 判断一组答案是否正确 */
    public static boolean isRightAnswer(Answer[] oneGroupAnswer) {
        List<Answer> rightAnswers = new ArrayList<>();
        for (Answer a : oneGroupAnswer) {
            if (rightAnswers.stream().anyMatch(rightAnswer ->
                    a.number == rightAnswer.number
                    || a.name.equals(rightAnswer.name))) {
                return false;
            }
            rightAnswers.add(a);
        }
        return true;
    }
}
运行结果如下:
[5甘肃, 2湖北, 1山东, 4吉林, 3陕西]
  • 打赏
  • 举报
回复
看了各位的代码,感觉Java好厉害,善于把简单问题复杂化,复杂问题更复杂,增加了程序员的需求,促进了就业,双赢!
android_cai_niao 2021-04-20
  • 打赏
  • 举报
回复
暴力破解来了,经常半天思考,总于把暴力破解做出来了,难点在于如何把答案的所有组合计算出来,正是这个难题花了我大量时间,示例说明如下: A 1 2 B 3 4 C 5 6 先假设有A、B、C三个同学,每个同学给出了两个答案,则答案组合的数量有8个(2的3次幂),所有答案组合如下: 1、3、5 1、3、6 1、4、5 1、4、6 2、3、5 2、3、6 2、4、5 2、4、6 这就是暴力破解,所有的答案组合都列出来了,正确答案肯定在这8组答案里面,所以,只要能把所有组合计算出来,验证一下哪组是正确答案即可。 代码如下:

// 定义一个Answer类来表示一个答案
data class Answer(val number: Int, val name: String) {
    override fun toString() = "$number$name"
}

fun main() {
    val allAnswers = arrayOf(
        arrayOf(Answer(1, "一"), Answer(3, "五")),
        arrayOf(Answer(2, "二"), Answer(1, "五")),
        arrayOf(Answer(3, "三"), Answer(3, "五")),
        arrayOf(Answer(4, "四"), Answer(4, "五")),
        arrayOf(Answer(5, "五"), Answer(5, "四"))
    )

    val answerSheet = getAnswerSheet(allAnswers)
    val rightAnswer = findRightAnswers(answerSheet)
    rightAnswer.forEach { println(it.contentToString()) }
}

private fun getAnswerSheet(allAnswers: Array<Array<Answer>>): Array<Array<Answer>> {
    // 计算答案表的大小为:2的allAnswers.size次幂
    val sheetSize = 2.0.pow(allAnswers.size).toInt()
    // 创建答案表
    val answerSheet = Array(sheetSize) { Array(allAnswers.size) { Answer(0, "") } }
    // 遍历所有答案,并填充到答案表中
    allAnswers.forEachIndexed { outIndex, answers ->
        // 计算答案可以连续填充的最大次数
        val maxPutCount = 2.0.pow((allAnswers.size - 1 - outIndex).toDouble()).toInt()
        answers.forEachIndexed { index, answer ->
            var putCount = 0
            for (i in answerSheet.indices) {
                if (++putCount <= maxPutCount) {
                    answerSheet[i + index * maxPutCount][outIndex] = answer
                } else if (putCount % maxPutCount == 0) {
                    putCount = 0
                }
            }
        }
    }
    return answerSheet
}

/** 找到答案表中的所有正确答案 */
fun findRightAnswers(answerSheet: Array<Array<Answer>>): List<Array<Answer>> {
    val rightAnswer = mutableListOf<Array<Answer>>()
    // 遍历每一组答案,并验证是否正确
    answerSheet.forEach { oneGroupAnswer ->
        if (isRightAnswer(oneGroupAnswer)) {
            rightAnswer.add(oneGroupAnswer)
        }
    }
    return rightAnswer
}

/** 判断一组答案是否正确 */
fun isRightAnswer(oneGroupAnswer: Array<Answer>): Boolean {
    val rightAnswers = mutableListOf<Answer>()
    oneGroupAnswer.forEach { answer ->
        if (rightAnswers.any { it.number == answer.number || it.name == answer.name }) {
            return false
        }
        rightAnswers.add(answer)
    }
    return true
}
运行结果如下:

[1一, 2二, 3三, 4四, 5五]
[1一, 2二, 3三, 4五, 5四]
通过这个暴力破解,还发现了这里出的题是有问题的,正确答案有两个。所以,如果你出题有多个正确答案,通过暴力破解轻松可以计算出来,如果用别的方式就困难多了。
老王就是我 2021-04-20
  • 打赏
  • 举报
回复
1、山东 2、湖北 3、夏西 4、吉林 5、甘肃。 首先统计出唯一出现过的省份和编号(假设为三号童鞋),然后计算出三号童鞋猜对的那个省份的位置(因为肯定是错的),如此重复,懂了吧
qq_39936465 2021-04-20
  • 打赏
  • 举报
回复
引用 楼主 qq_29448025 的回复:
java书上选择结构章节后,有一个课后习题,题目描述是下面这样的: 这个选择结构是算不出来的吧。如果有别的思路,如循环和数组,大家也请指出,能解出来也行。

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Map<Integer, String> map =new HashMap<>();
		List<List<Demo>> list = new ArrayList<List<Demo>>();
		List<Demo> demo = new ArrayList<Demo>();
		demo.add(new Demo(2, "陕西"));
		demo.add(new Demo(5, "甘肃"));
		list.add(demo);
		demo = new ArrayList<Demo>();
		demo.add(new Demo(2, "湖北"));
		demo.add(new Demo(4, "山东"));
		list.add(demo);
		demo = new ArrayList<Demo>();
		demo.add(new Demo(1, "山东"));
		demo.add(new Demo(5, "吉林"));
		list.add(demo);
		demo = new ArrayList<Demo>();
		demo.add(new Demo(3, "湖北"));
		demo.add(new Demo(4, "吉林"));
		list.add(demo);
		demo = new ArrayList<Demo>();
		demo.add(new Demo(2, "甘肃"));
		demo.add(new Demo(3, "陕西"));
		list.add(demo);
		demo = new ArrayList<Demo>();
		boolean flag = true ;
		int t = 0;
		while(t < 2&&flag ) {
			map.put(list.get(0).get(t).getKey(), list.get(0).get(t).getValue());
			for (int i = 1 ; i < 5 ; i ++) {
				demo = list.get(i);
				if (!map.containsKey(demo.get(0).getKey()) && !map.containsValue(demo.get(0).getValue())) {
					map.put(demo.get(0).getKey(),demo.get(0).getValue());
				}else if(!map.containsKey(demo.get(1).getKey())&&!map.containsValue(demo.get(1).getValue())){
					map.put(demo.get(1).getKey(), demo.get(1).getValue());
				}else {
					map.clear();
					break;
				}
				if (i == 4 &&flag == true) flag=false;
			}
			t++;
		}
		Iterator<Entry<Integer, String>> iterator = map.entrySet().iterator();
		while(iterator.hasNext()) {
			Entry<Integer, String> entry = iterator.next();
			System.out.println(entry.getKey()+"号是" +entry.getValue());
		}
	}
}

class Demo {
	private Integer key;
	private String value;
	/**
	 * @param key
	 * @param value
	 */
	public Demo(int key, String value) {
		this.key = key;
		this.value = value;
	}
	public int getKey() {
		return key;
	}
	public void setKey(int key) {
		this.key = key;
	}
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		this.value = value;
	}
	@Override
	public String toString() {
		return "Demo [key=" + key + ", value=" + value + "]";
	}
}

android_cai_niao 2021-04-19
  • 打赏
  • 举报
回复
像这种情况的话,感觉得像2楼说的那样,使用暴力破解,把所有组合算出来,然后一一匹对,但是这暴力破解说的简单,写起来似乎也挺难的。
android_cai_niao 2021-04-19
  • 打赏
  • 举报
回复
如果按照每条正确答案一定能找到一条对应错误答案的话,解这题还是比较简单的。但是,如果通过一条正确答案没有对应的错误答案的话,好像就难许多了,为了题目更清晰,我用1对一,2对二这样的方式出题,比较容易出题,如下: A 1 一, 3 五 B 2 二, 1 五 C 3 三, 3 五 D 4 四, 4 五 E 5 五, 5 四 正确答案为: 1 一 2 二 3 三 4 四 5 五 我之前的解题是按每一个正确答案必能推出错误答案来解的,如果用来解这道题的话就行不能,比如假设A同学的第一个答案正确,则可以推出B同学的1五答案是错误的,则B同学2二答案是对的,但是通过B同学的正确答案2二答案就没办法找到其他错误答案了
lxf412096 2021-04-19
  • 打赏
  • 举报
回复
这个问题以前也遇到过,今天在这里学习了!
android_cai_niao 2021-04-19
  • 打赏
  • 举报
回复
6楼逻辑确实是有问题的,洽好碰到了好的答案,像下面这种就找不出来了,如下: A 1-山东, 1-甘肃 B 2-湖北, 2-山东 C 3-陕西, 2-甘肃 D 4-吉林, 5-湖北 E 5-甘肃, 3-吉林 正确答案为: A 1-山东 B 2-湖北 C 3-陕西 D 4-吉林 E 5-甘肃
qq_29448025 2021-04-18
  • 打赏
  • 举报
回复
引用 6 楼 尼坤神 的回复:


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

/**
 * A、B、C、D、E    五位同学
 * 1、2、3、4、5    五个省份
 * <p>
 * A: 2 -> 陕西  5 -> 甘肃
 * B: 2 -> 湖北  4 -> 山东
 * C: 1 -> 山东  5 -> 吉林
 * D: 3 -> 湖北  4 -> 吉林
 * E: 2 -> 甘肃  3 -> 陕西
 * <p>
 * 每位同学答对一个省份,并且每个编号只有一位同学答对,问1-5号省份对应的名称
 */
public class Reasoning {

    /**
     * 同学
     */
    private static List<String> students = new ArrayList<>(5);
    /**
     * 城市
     */
    private static Map<Integer, String> citys = new HashMap<>(5);
    /**
     * 证词
     */
    private static Map<String, Map<Integer, String>> testimony = new HashMap<>();

    public static void main(String[] args) {
        Reasoning reasoning = new Reasoning();
        reasoning.prove();
        System.out.println("最终得出:" + citys);
    }

    public Reasoning() {
        students = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E"));
        Map<Integer, String> A = new HashMap<>();
        A.put(2, "陕西");
        A.put(5, "甘肃");
        testimony.put("A", A);

        Map<Integer, String> B = new HashMap<>();
        B.put(2, "湖北");
        B.put(4, "山东");
        testimony.put("B", B);

        Map<Integer, String> C = new HashMap<>();
        C.put(1, "山东");
        C.put(5, "吉林");
        testimony.put("C", C);

        Map<Integer, String> D = new HashMap<>();
        D.put(3, "湖北");
        D.put(4, "吉林");
        testimony.put("D", D);

        Map<Integer, String> E = new HashMap<>();
        E.put(2, "甘肃");
        E.put(3, "陕西");
        testimony.put("E", E);
    }

    /**
     * 开始证明
     * <p>
     * 1.假设 A 答对 第一句
     */
    private void prove() {
        boolean check = true;
        for (String student : students) {
            Map<Integer, String> city = testimony.get(student);
            boolean flag = false;
            for (Integer cityCode : city.keySet()) {
                String tempCityName = city.get(cityCode);
                if (checkCity(student, cityCode, tempCityName)) {
                    flag = true;
                    break;
                }
            }
            if (!flag) {
                check = false;
                System.out.println("学生" + student + "证词" + city + "没有得到验证。");
                break;
            }
        }
        // 冲突,前面假设出错
        if (!check) {
            citys.clear();
            System.out.println("前期猜想出错,重新开始!");
            revisionStu();
            prove();
        }
    }

    /**
     * 验证猜想
     *
     * @param student      学生
     * @param cityCode     城市代码
     * @param tempCityName 城市名称
     * @return 是否符合验证
     */
    private boolean checkCity(String student, Integer cityCode, String tempCityName) {
        String cityName = citys.get(cityCode);
        if ((cityName == null || cityName.equals(tempCityName)) && !citys.containsValue(tempCityName)) {
            citys.put(cityCode, tempCityName);
            System.out.println("学生" + student + "证词:" + cityCode + "是" + tempCityName);
            return true;
        }
        return false;
    }

    /**
     * 调整学生顺序
     */
    private void revisionStu() {
        String stu = students.get(0);
        students.remove(stu);
        students.add(stu);
    }
}
首先感谢你的回答,你的答案,我研究了半天,觉得有点小问题,那就是如果每个人的第一个答案都不正确(理论上有可能),就会陷入无限循环。 还有,假设第一个人的第一个答案正确,后面验证不通过,也并不能说明第一个人的第一个答案是错误的,因为后面验证不通过,也可能是其它几个人的回答自相矛盾的问题。 你的代码,我改了下,用的LinkedHashMap(以方便记住顺序),把每个人的答案顺序调了下(答案内容不变),即正确答案都是后面第二个(或者大多数都在后面第二个),就陷入递归层次太多,内存溢出了。 改动代码如下:
package chapter4;
import java.util.*;

/**
 * A、B、C、D、E    五位同学
 * 1、2、3、4、5    五个省份
 * <p>
 * A: 2 -> 陕西  5 -> 甘肃
 * B: 2 -> 湖北  4 -> 山东
 * C: 1 -> 山东  5 -> 吉林
 * D: 3 -> 湖北  4 -> 吉林
 * E: 2 -> 甘肃  3 -> 陕西
 * <p>
 * 每位同学答对一个省份,并且每个编号只有一位同学答对,问1-5号省份对应的名称
 */
public class Reasoning {

    /**
     * 同学
     */
    private static List<String> students = new ArrayList<>(5);
    /**
     * 城市
     */
    private static Map<Integer, String> citys = new HashMap<>(5);
    /**
     * 证词
     */
    private static Map<String, Map<Integer, String>> testimony = new HashMap<>();

    public static void main(String[] args) {
        Reasoning reasoning = new Reasoning();
        reasoning.prove();
        System.out.println("最终得出:" + citys);
    }

    public Reasoning() {
        students = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E"));
        Map<Integer, String> A = new LinkedHashMap<>();
        A.put(2, "陕西");
        A.put(5, "甘肃");
        testimony.put("A", A);

        Map<Integer, String> B = new LinkedHashMap<>();
        B.put(4, "山东");
        B.put(2, "湖北");
        testimony.put("B", B);

        Map<Integer, String> C = new LinkedHashMap<>();
        C.put(5, "吉林");
        C.put(1, "山东");
        testimony.put("C", C);

        Map<Integer, String> D = new LinkedHashMap<>();
        D.put(4, "吉林");
        D.put(3, "湖北");
        testimony.put("D", D);

        Map<Integer, String> E = new LinkedHashMap<>();
        E.put(2, "甘肃");
        E.put(3, "陕西");
        testimony.put("E", E);
    }

    /**
     * 开始证明
     * <p>
     * 1.假设 A 答对 第一句
     */
    private void prove() {
        boolean check = true;
        for (String student : students) {
            Map<Integer, String> city = testimony.get(student);
            boolean flag = false;
            for (Integer cityCode : city.keySet()) {
                String tempCityName = city.get(cityCode);
                if (checkCity(student, cityCode, tempCityName)) {
                    flag = true;
                    break;
                }
            }
            if (!flag) {
                check = false;
                System.out.println("学生" + student + "证词" + city + "没有得到验证。");
                break;
            }
        }
        // 冲突,前面假设出错
        if (!check) {
            citys.clear();
            System.out.println("前期猜想出错,重新开始!");
            revisionStu();
            prove();
        }
    }

    /**
     * 验证猜想
     *
     * @param student      学生
     * @param cityCode     城市代码
     * @param tempCityName 城市名称
     * @return 是否符合验证
     */
    private boolean checkCity(String student, Integer cityCode, String tempCityName) {
        String cityName = citys.get(cityCode);
        if ((cityName == null || cityName.equals(tempCityName)) && !citys.containsValue(tempCityName)) {
            citys.put(cityCode, tempCityName);
            System.out.println("学生" + student + "证词:" + cityCode + "是" + tempCityName);
            return true;
        }
        return false;
    }

    /**
     * 调整学生顺序
     */
    private void revisionStu() {
        String stu = students.get(0);
        students.remove(stu);
        students.add(stu);
    }
}
qq_29448025 2021-04-18
  • 打赏
  • 举报
回复
感谢各位的热心回复,我这段时间得静下心,好好学习了。
android_cai_niao 2021-04-17
  • 打赏
  • 举报
回复
这道题简单并不难,这里我使用Kotlin语言实现,不懂kotlin也没关系,看完我的思路之后,你自己用Java代码来实现一次完全可以的,这时你会发现java实现起来比kotlin的代码要多很多,这就是为什么Google在2017年的时候把Kotlin当成Android开发的官方语言了,大家有时间也应该学习一下Kotlin,只要是使用java开发的(比如后端开发),都可以使用kotlin来替换的,因为Kotlin最终编译后也是class字节码,底层其实就是java。我的实现代码没多少,我写了很多注释,还有空行,看起来多,其实重点只有 findAllRightAnswers() 函数,大概13行代码左右,看懂此函数就相当于整个题都懂了,代码如下

// 定义一个Answer类来表示一个答案
data class Answer(val number: Int, val name: String)

// 定义一个Student类来表示一个同学
data class Student(val first: Answer, val second: Answer)

fun main() {
    // 定义A、B、C、D、E五个同学
    val A = Student(Answer(2, "陕西"), Answer(5, "甘肃"))
    val B = Student(Answer(2, "湖北"), Answer(4, "山东"))
    val C = Student(Answer(1, "山东"), Answer(5, "吉林"))
    val D = Student(Answer(3, "湖北"), Answer(4, "吉林"))
    val E = Student(Answer(2, "甘肃"), Answer(3, "陕西"))

    // 定义一个集合,保存未知正确答案的所有同学
    var unknownAnswerStudentList = mutableListOf(A, B, C, D, E)
    // 定义保存正确答案的集合
    val rightAnswerList = mutableListOf<Answer>()
    // 假设第一个人的第一个答案是正确答案,保存到正确答案集合中
    rightAnswerList.add(A.first)
    // 因为找到A同学的正确答案了,所以把A同学从集合中移除
    unknownAnswerStudentList.remove(A)
    // 找到所有正确答案
    findAllRightAnswers(unknownAnswerStudentList, rightAnswerList, unknownAnswerStudentList.size)

    if (rightAnswerList.size == 5) {
        println("第一次假设就找到了正确答案,如下:")
    } else {
        println("第一次假设找不到正确答案,第二次肯定是正确答案,如下:")
        // 没找齐5个答案,说明最初假设的答案是错的,则另一个必定是正确答案,重新找
        unknownAnswerStudentList = mutableListOf(A, B, C, D, E)
        rightAnswerList.clear()
        rightAnswerList.add(A.second) // 假设另一个为正确答案
        unknownAnswerStudentList.remove(A)
        findAllRightAnswers(unknownAnswerStudentList, rightAnswerList, unknownAnswerStudentList.size)
    }

    // 打印正确答案
    rightAnswerList.forEach(System.out::println)

}

fun findAllRightAnswers(unknownAnswerStudentList: MutableList<Student>, rightAnswerList: MutableList<Answer>, findCount: Int) {
    // 遍历每一个同学,使用iterator是因为在遍历集合的同时还要删除集合的元素。
    val iterator = unknownAnswerStudentList.iterator()

    while (iterator.hasNext()) {
        val student = iterator.next()

        // 通过正确答案找正确答案
        if (rightAnswerList.any { student.first.number == it.number || student.first.name == it.name }) {
            // 如果第一个答案的编号或名称与正确答案的相同,根据"每个编号只有一个人答对"说明这个是错误答案,则第二个答案可能是正确答案
            if (rightAnswerList.any { student.second.number == it.number || student.second.name == it.name }) {
                // 如果第二个答案的编号或名称与正确答案相同,说明这个也是错误答案,说明我们的假设是错误的,无解,退出循环
                break
            }

            rightAnswerList.add(student.second) // 找到了正确答案
            iterator.remove()                   // 此学生已找到正确答案,可以从集合中移除掉了
        } else if (rightAnswerList.any { student.second.number == it.number || student.second.name == it.name }) {
            // 如果第二个答案的编号与正确答案的相同,根据"每个编号只有一个人答对"说明这个是错误答案,则第一个答案可能是正确答案
            if (rightAnswerList.any { student.first.number == it.number || student.first.name == it.name }) {
                // 如果第一个答案的编号或名称与正确答案相同,说明这个也是错误答案,说明我们的假设是错误的,无解,退出循环
                break
            }

            rightAnswerList.add(student.first) // 找到了正确答案
            iterator.remove()                  // 此学生已找到正确答案,可以从集合中移除掉了
        }
    }

    if (unknownAnswerStudentList.size > 0 && findCount - 1 > 0) {
        // 如果还有同学没找到正确答案,且没有超过查找次数,则递归循环去找
        // 设定查找次数是因为如果你假设的答案是错误的,则永远也找不齐5个正确答案造成死循环
        findAllRightAnswers(unknownAnswerStudentList, rightAnswerList, findCount - 1)
    }
}

运行结果如下:

第一次假设找不到正确答案,第二次肯定是正确答案,如下:
Answer(number=5, name=甘肃)
Answer(number=1, name=山东)
Answer(number=3, name=陕西)
Answer(number=2, name=湖北)
Answer(number=4, name=吉林)
觉得难的同学都是Java基础不扎实造成的,大家可以关注我的博客,多多交流:https://blog.csdn.net/android_cai_niao 我也是第一次看到这道题,刚看到题时确实觉得有点难,但是当把题目审清楚理解清楚之后就很简单了,写代码的时候再使用面向对象的方式去写就非常的简单,比如一个学生用Student表示,而答案是一个学生的属性;一个答案用Answer表示,编号和省份是Answer的属性,大家一定要经常面向对象去写代码,不然你可能虽然有思路了,但是总感觉代码一写就觉得怎么没那么简单了!那是因为你的代码是面向过程的,不是面向对象的。 这里给大家讲一下我对题目的理解:每个同学都有两个答案,且肯定有一个是对的,有一个是错的,而且这个同学的正确答案肯定在另一个同学里有错误答案,这样才能推出这个同学的正确答案,比如: A同学 2-陕西,5-甘肃 E同学 2-甘肃,3-陕西 我们就只看这两个同学,假设A同学的2-陕西是正确答案,根据"每个编号只有一个同学答对"的规则,可知2-甘肃是错的,因为2号只会对应到一个正确的省份陕西,反过来,陕西对应到了2号,则3-陕西也是错误答案了,什么?E同学的两个答案都是错误的?没错,就是这样的,存在这种情况是因为我们随便假设了一个答案为真,出现一个同学两答案都不正确的话,说明我们的假设出错了,出现了无解,此时再假设另一个答案为正确答案肯定就是对的了,因此,细节就是,通过一个正确答案的编号或省份名称都可以找到错误的答案,然后通过错误答案另一个自然就是正确答案了。 说了这么多,简单总结一下思路就是:随便假设一个是正确答案,我们可以通过一个正确答案找到错误答案,通过此错误答案又得到另一个正确答案,再通过这个正确答案再找错误答案,一直循环找就行了 ,总体思路是很简单的,就是细节上代码逻辑容易写错,慢慢调试就好了,关键总体思路不能乱! 最后再提醒一点,写代码一定要面向对象去写,很重要哦!
sotondolphin 2021-04-15
  • 打赏
  • 举报
回复
看看你能理解吗?

public class GuessProvinces {
    private static Map<Integer, String> answerMap =
            new HashMap<>();

    private static Map<String,List<String>> guessesMap = new HashMap<>();
    private static Map<Integer, String> SA = new HashMap<>();
    private static Map<Integer, String> SB = new HashMap<>();
    private static Map<Integer, String> SC = new HashMap<>();
    private static Map<Integer, String> SD = new HashMap<>();
    private static Map<Integer, String> SE = new HashMap<>();
    static {
        SA.put(2, "SHANXI");
        SA.put(5, "GANSU");

        SB.put(2, "HUBEI");
        SB.put(4, "SHANDONG");

        SC.put(1, "SHANDONG");
        SC.put(5, "JILIN");

        SD.put(3, "HUBEI");
        SD.put(4, "JILIN");

        SE.put(2, "GANSU");
        SE.put(3, "SHANXI");
    }
    public static void main(String[] args) {
        String StudentA_1 = "01000"; //0
        String StudentA_2 = "00001"; //1
        List<String> StudentA = new ArrayList<>();
        StudentA.add(StudentA_1);
        StudentA.add(StudentA_2);

        String StudentB_1 = "01000"; //2
        String StudentB_2 = "00010"; //3
        List<String> StudentB = new ArrayList<>();
        StudentB.add(StudentB_1);
        StudentB.add(StudentB_2);

        String StudentC_1 = "10000"; //4
        String StudentC_2 = "00001"; //5
        List<String> StudentC = new ArrayList<>();
        StudentC.add(StudentC_1);
        StudentC.add(StudentC_2);

        String StudentD_1 = "00100"; //6
        String StudentD_2 = "00010"; //7
        List<String> StudentD = new ArrayList<>();
        StudentD.add(StudentD_1);
        StudentD.add(StudentD_2);

        String StudentE_1 = "01000"; //8
        String StudentE_2 = "00100"; //9
        List<String> StudentE = new ArrayList<>();
        StudentE.add(StudentE_1);
        StudentE.add(StudentE_2);

        guessesMap.put("A", StudentA);
        guessesMap.put("B", StudentB);
        guessesMap.put("C", StudentC);
        guessesMap.put("D", StudentD);
        guessesMap.put("E", StudentE);

        List<String> guesses = guessesMap.values()
                .stream()
                .flatMap(List::stream)
                .collect(Collectors.toList());
        int charPosition = 0;
        while(answerMap.size() != 5){
            if (charPosition > 4){
                charPosition = 0;
            }
            guesses = guessesMap.values()
                    .stream()
                    .flatMap(List::stream)
                    .collect(Collectors.toList());
            int oneCounter = 0;
            String guessHit = null;
            for(String guess : guesses){
                if(guess.charAt(charPosition) == '1'){
                    oneCounter++;
                    guessHit = guess;
                }
            }
            if(oneCounter == 1){
                removeInvalidGuess(guessHit);
            }else{
                checkAgainstAnswerMap();
            }

            charPosition ++;
            System.out.println(answerMap);
        }
        System.out.println("Comparison is done");
    }
    private static void removeInvalidGuess(String guessHit){
        for(Map.Entry<String, List<String>> entry : guessesMap.entrySet()){
            if(entry.getValue().contains(guessHit)){
                guessesMap.put(entry.getKey(), Arrays.asList(guessHit));
                updateAnswerMap(entry.getKey(), guessHit);
            }
        }
    }

    private static void updateAnswerMap(String student, String answers){
        int answerIndex = answers.indexOf("1") + 1;

        switch (student){
            case "A":
                answerMap.put(answerIndex, SA.get(answerIndex));
                break;
            case "B":
                answerMap.put(answerIndex, SB.get(answerIndex));
                break;
            case "C":
                answerMap.put(answerIndex, SC.get(answerIndex));
                break;
            case "D":
                answerMap.put(answerIndex, SD.get(answerIndex));
                break;
            case "E":
                answerMap.put(answerIndex, SE.get(answerIndex));
                break;
        }
    }
    private static void checkAgainstAnswerMap(){
        for(Map.Entry<String, List<String>> studentGuess : guessesMap.entrySet()){
            String student = studentGuess.getKey();
            List<String> answers = studentGuess.getValue();
            if (answers.size() == 1){
                return;
            }
            switch (student){
                case "A":
                    for(String answer: answers){
                        int answerKey = answer.indexOf("1") + 1;
                        String studentAnswer = SA.get(answerKey);
                        Integer correctAnswerKey = (getKey(answerMap, studentAnswer));
                        if(correctAnswerKey!= null && answerKey != correctAnswerKey.intValue()){
                            guessesMap.get(student).remove(answer);
                            break;
                        }
                    }
                    break;
                case "B":
                    for(String answer: answers){
                        int answerKey = answer.indexOf("1") + 1;
                        String studentAnswer = SB.get(answerKey);
                        Integer correctAnswerKey = (getKey(answerMap, studentAnswer));
                        if(correctAnswerKey!= null && answerKey != correctAnswerKey.intValue()){
                            guessesMap.get(student).remove(answer);
                            break;
                        }
                    }
                    break;
                case "C":
                    for(String answer: answers){
                        int answerKey = answer.indexOf("1") + 1;
                        String studentAnswer = SC.get(answerKey);
                        Integer correctAnswerKey = (getKey(answerMap, studentAnswer));
                        if(correctAnswerKey!= null && answerKey != correctAnswerKey.intValue()){
                            guessesMap.get(student).remove(answer);
                            break;
                        }
                    }
                    break;
                case "D":
                    for(String answer: answers){
                        int answerKey = answer.indexOf("1") + 1;
                        String studentAnswer = SD.get(answerKey);
                        Integer correctAnswerKey = (getKey(answerMap, studentAnswer));
                        if(correctAnswerKey!= null && answerKey != correctAnswerKey.intValue()){
                            guessesMap.get(student).remove(answer);
                            break;
                        }
                    }
                    break;
                case "E":
                    for(String answer: answers){
                        int answerKey = answer.indexOf("1") + 1;
                        String studentAnswer = SE.get(answerKey);
                        Integer correctAnswerKey = (getKey(answerMap, studentAnswer));
                        if(correctAnswerKey!= null && answerKey != correctAnswerKey.intValue()){
                            guessesMap.get(student).remove(answer);
                            break;
                        }
                    }
                    break;
            }
        }
    }
    public static <K, V> K getKey(Map<K, V> map, V value)
    {
        return map.entrySet()
                .stream()
                .filter(entry -> value.equals(entry.getValue()))
                .map(Map.Entry::getKey)
                .findFirst().orElse(null);
    }
}

最后结果 {1=SHANDONG, 2=HUBEI, 3=SHANXI, 4=JILIN, 5=GANSU}
nayi_224 2021-04-15
  • 打赏
  • 举报
回复
首先要注意每一个人包含两条信息,一个对的,一个错的。 然后做一个全排列组合,标识出每一个人的第一个回答是否正确,就像这样 11111 11110 11100... 一共5!个 之后可以用set之类的简化操作,查看每个人认为对的里面是否包含全部5个省份,再用认为错误的里面进行校验。 用眼睛去看,结果应该是这样的

A 2-陕 5-甘 --->	5-甘
B 2-湖 4-山 --->	2-湖
C 1-山 5-吉 --->	1-山
D 3-湖 4-吉 --->	4-吉
E 2-甘 3-陕 --->	3-陕
尼坤神 2021-04-15
  • 打赏
  • 举报
回复


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

/**
 * A、B、C、D、E    五位同学
 * 1、2、3、4、5    五个省份
 * <p>
 * A: 2 -> 陕西  5 -> 甘肃
 * B: 2 -> 湖北  4 -> 山东
 * C: 1 -> 山东  5 -> 吉林
 * D: 3 -> 湖北  4 -> 吉林
 * E: 2 -> 甘肃  3 -> 陕西
 * <p>
 * 每位同学答对一个省份,并且每个编号只有一位同学答对,问1-5号省份对应的名称
 */
public class Reasoning {

    /**
     * 同学
     */
    private static List<String> students = new ArrayList<>(5);
    /**
     * 城市
     */
    private static Map<Integer, String> citys = new HashMap<>(5);
    /**
     * 证词
     */
    private static Map<String, Map<Integer, String>> testimony = new HashMap<>();

    public static void main(String[] args) {
        Reasoning reasoning = new Reasoning();
        reasoning.prove();
        System.out.println("最终得出:" + citys);
    }

    public Reasoning() {
        students = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E"));
        Map<Integer, String> A = new HashMap<>();
        A.put(2, "陕西");
        A.put(5, "甘肃");
        testimony.put("A", A);

        Map<Integer, String> B = new HashMap<>();
        B.put(2, "湖北");
        B.put(4, "山东");
        testimony.put("B", B);

        Map<Integer, String> C = new HashMap<>();
        C.put(1, "山东");
        C.put(5, "吉林");
        testimony.put("C", C);

        Map<Integer, String> D = new HashMap<>();
        D.put(3, "湖北");
        D.put(4, "吉林");
        testimony.put("D", D);

        Map<Integer, String> E = new HashMap<>();
        E.put(2, "甘肃");
        E.put(3, "陕西");
        testimony.put("E", E);
    }

    /**
     * 开始证明
     * <p>
     * 1.假设 A 答对 第一句
     */
    private void prove() {
        boolean check = true;
        for (String student : students) {
            Map<Integer, String> city = testimony.get(student);
            boolean flag = false;
            for (Integer cityCode : city.keySet()) {
                String tempCityName = city.get(cityCode);
                if (checkCity(student, cityCode, tempCityName)) {
                    flag = true;
                    break;
                }
            }
            if (!flag) {
                check = false;
                System.out.println("学生" + student + "证词" + city + "没有得到验证。");
                break;
            }
        }
        // 冲突,前面假设出错
        if (!check) {
            citys.clear();
            System.out.println("前期猜想出错,重新开始!");
            revisionStu();
            prove();
        }
    }

    /**
     * 验证猜想
     *
     * @param student      学生
     * @param cityCode     城市代码
     * @param tempCityName 城市名称
     * @return 是否符合验证
     */
    private boolean checkCity(String student, Integer cityCode, String tempCityName) {
        String cityName = citys.get(cityCode);
        if ((cityName == null || cityName.equals(tempCityName)) && !citys.containsValue(tempCityName)) {
            citys.put(cityCode, tempCityName);
            System.out.println("学生" + student + "证词:" + cityCode + "是" + tempCityName);
            return true;
        }
        return false;
    }

    /**
     * 调整学生顺序
     */
    private void revisionStu() {
        String stu = students.get(0);
        students.remove(stu);
        students.add(stu);
    }
}
nayi_224 2021-04-15
  • 打赏
  • 举报
回复
引用 1 楼 nayi_224 的回复:
首先要注意每一个人包含两条信息,一个对的,一个错的。 然后做一个全排列组合,标识出每一个人的第一个回答是否正确,就像这样 11111 11110 11100... 一共5!个 之后可以用set之类的简化操作,查看每个人认为对的里面是否包含全部5个省份,再用认为错误的里面进行校验。 用眼睛去看,结果应该是这样的

A 2-陕 5-甘 --->	5-甘
B 2-湖 4-山 --->	2-湖
C 1-山 5-吉 --->	1-山
D 3-湖 4-吉 --->	4-吉
E 2-甘 3-陕 --->	3-陕
尴尬,高中数学竟然算错了,应该是2^5
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Test03 {

	public static void main(String[] args) {
		String[][] src = {
			{"2", "陕", "5", "甘"},
			{"2", "湖", "4", "山"},
			{"1", "山", "5", "吉"},
			{"3", "湖", "4", "吉"},
			{"2", "甘", "3", "陕"},
		};
        List<String> list1 = Arrays.asList("1", "0");
        
        List<List<String>> list = new ArrayList();
        list.add(list1);
        list.add(list1);
        list.add(list1);
        list.add(list1);
        list.add(list1);
        
        List<List<String>> result = new ArrayList<List<String>>();
		
        descartes(list, result, 0, new ArrayList<String>());
        Map<String, String> map = new HashMap();
        Set<String> set = new HashSet();
        a: for(List<String> res: result){
        	map = new HashMap();
        	set = new HashSet();
        	for(int i = 0; i < res.size(); i++){
        		if("1".equals(res.get(i)))
        			map.put(src[i][0], src[i][1]);
        		else
        			map.put(src[i][2], src[i][3]);
        	}
        	if(map.size() < 5)
        		continue;
        	set.addAll(map.values());
        	if(set.size() < 5)
        		continue;
        	
        	for(int i = 0; i < res.size(); i++){
        		if("0".equals(res.get(i))){
        			if(map.get(src[i][0]).equals(src[i][1])){
        				continue a;
        			}
        		}else{
        			if(map.get(src[i][2]).equals(src[i][3])){
        				continue a;
        			}
        		}
        	}
        	prt(src, res);
        }
        
	}
	
	private static void prt(String[][] src, List<String> list){
		for(int i = 0; i < list.size(); i++){
			if("1".equals(list.get(i)))
				System.out.print(src[i][0] + "-" + src[i][1] + ", ");
			else
				System.out.print(src[i][2] + "-" + src[i][3] + ", ");
		}
		System.out.println();
	}
	
	private static void descartes(List<List<String>> dimvalue, List<List<String>> result, int layer, List<String> curList) {
        if (layer < dimvalue.size() - 1) {
            if (dimvalue.get(layer).size() == 0) {
                descartes(dimvalue, result, layer + 1, curList);
            } else {
                for (int i = 0; i < dimvalue.get(layer).size(); i++) {
                    List<String> list = new ArrayList<String>(curList);
                    list.add(dimvalue.get(layer).get(i));
                    descartes(dimvalue, result, layer + 1, list);
                }
            }
        } else if (layer == dimvalue.size() - 1) {
            if (dimvalue.get(layer).size() == 0) {
                result.add(curList);
            } else {
                for (int i = 0; i < dimvalue.get(layer).size(); i++) {
                    List<String> list = new ArrayList<String>(curList);
                    list.add(dimvalue.get(layer).get(i));
                    result.add(list);
                }
            }
        }
    }

}
i__0o0__ 2021-04-15
  • 打赏
  • 举报
回复
用选择结构没有问题,就是用选择结构列出了所有可能的情况,然后每个情况判断是否合理,合理就继续走,不合理就返回,执行另外的分支,把所有条件都走一遍就是了

if(A的第一句是对的){
    if(B的第一句是对的){
        if(C的第一句是对的){
             if(D的第一句是对的){
                   if(E的第一句是对的){
                          //验证合理性
                   }else{ //E的第二句的是对的
                          //验证合理性
                    }
             }else{ //D的第二句的是对的

             }
        }else{ //C的第二句的是对的

        }
    }else{ //A的第二句是对的

   }
}else{  //A的第二句是对的

}
sotondolphin 2021-04-15
  • 打赏
  • 举报
回复
从给的答案,很容易判断1和5是哪个省份。然后再根据1和5的值去排除其他的错误答案。

62,635

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧