黑马程序员技术交流社区
标题:
用Java编程解决一道逻辑推理题
[打印本页]
作者:
飞鸟青崖
时间:
2013-6-2 16:34
标题:
用Java编程解决一道逻辑推理题
本帖最后由 飞鸟青崖 于 2013-6-3 11:37 编辑
题目:
有4名同学参加数学竞赛,3个老师对他们的名次进行的预测。每一个老师
只预测两个同学的排名
。而竞赛结果表明每一个
老师都预测对了一半
。编写一个程序,使它能能根据老师的预测得到正确的结果。
注意:
老师的预测内容是不固定的。但老师的人数是固定的,只有3个。学生的人数也是固定的,只有4个。并且一定可以根据老师的预测得到正确的排名。
作者:
风云
时间:
2013-6-2 17:55
package mytest;
import java.util.Scanner;
public class Test14 {
/**
* 竞赛结果表明,他们都说对了一半,说错了一半,并且无并列名次,试编程输出a,b,c,d的各个名次。
* 分析:
* 我们将老师的预测列成二维数组形式。行数是老师的人数,也就是3.列数为5。
* 第一列表示该老师预测对的个数。由于一个老师预测了两部分,所以将初始值都设置为2.
* 我们首先假设第一个老师的第一部分预测时对的,那么就需要将预测了同一人,预测了同一名次,
* 以及第一个老师的另一部分预测全部设置为null,并且将相应的预测数减1.直到某一个预测数为0时,
* 那么这个假设就是错误的。
* @param args
*/
public static void main(String[] args) {
String[][] str = new String[3][5];
for(int x = 0;x<3;x++){
str[x][0] = 2+"";
}
System.out.println("注意:输入时人与名次用等号连接,人与人之间用逗号隔开。");
for(int x = 1;x<=3;x++){
System.out.print("请输入第"+x+"个老师的预测:");
Scanner sc = new Scanner(System.in);
String a = sc.next();
int firstd = a.indexOf("=");
int lastd = a.lastIndexOf("=");
int dou = a.indexOf(",");
str[x-1][Integer.parseInt(a.substring(firstd+1,dou))] = a.substring(0, firstd);
str[x-1][Integer.parseInt(a.substring(lastd+1))] = a.substring(dou+1, lastd);
}
String[][] bei = new String[3][5];//将数组备份,方便还原。
bei= fu(str,bei);
//由于第一个老师肯定会预测对一个,所以不需要进行行的遍历。
for(int y = 1;y<5;y++){
if(str[0][y] == null)
continue;
//假设第一个老师的当前预测是正确的,那么需要进行判断。
boolean b = hanshu(0,y,str);
//如果b是真的,那么就需要将所有的地方都进行一次判断。
//因为还有可能存在别的相矛盾的预测。
if(b){
k:for(int m = 1;m<3;m++){//第一个老师的正确预测已经假设过了,所以不需要从0开始。
for(int n = 1;n<5;n++)
if(str[m][n]!=null){
b = b&&hanshu(m,n,str);
if(!b)//如果某个预测出现了错误,那么就直接跳出循环即可。
break k;//跳出最外层,因为这个假设不对。
}
}
}
if(b){//如果当前假设成立,那么遍历输出相应的结果。
for(int x1 = 0;x1<3;x1++){
for(int y1 = 1;y1<5;y1++){
if(str[x1][y1]!=null)
System.out.println(str[x1][y1]+"是第"+y1+"名");
}
}
}
else{
if(y == 4){//当第一个老师的所有预测都是错误的时候,题目就无法完成了。
System.out.println("无法推断出名次。");
break;
}
str = fu(bei,str);//通过上面的操作,已经将str进行了改变,所以需要还原。
}
}
}
//改变同行、同列以及相同的人后,判断是不是出现错误。
private static boolean hanshu(int col, int row, String[][] str) {
boolean b= false;
for(int x = 0;x<3;x++){
for(int y = 1;y<5;y++){
b= false;//每一个位置开始时假设没有发生变化。
if(str[x][y]!=null){
if(x == col&&y!=row){//同行不同列
str[x][y] = null;
b = true;
}
else if( y == row&&x!=col){//同列不同行
str[x][y] = null;
b = true;
}
else if(str[x][y].equals(str[col][row])&&x!=col&&y!=row){//即不同列也不同行,但是预测的人是一样的。
str[x][y] = null;
b = true;
}
if(b){//如果该位置发生了变化,那么就将它所在的行的预测数减1.
str[x][0] = Integer.parseInt(str[x][0])-1+"";
if(str[x][0].equals("0"))
return false;
}
}
}
}
return true;
}
//将String[][]还原。
private static String[][] fu(String[][] o,String[][] b){
for(int x = 0;x<o.length;x++)
for(int y = 0;y<o[x].length;y++)
b[x][y] = o[x][y];
return b;
}
}
复制代码
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2