判断名次
问题描述
某场比赛过后,你想要知道A~E五个人的排名是什么,于是要求他们每个人说了一句话。(经典的开头……-_-!)得了第1名的人23,说了假话;得了第5名的人不好意思,也说了假话;为了使求解问题简单,第3名同样说了假话。(奇数名次说假话)
输入格式
共5行,各行依次表示A ~ E说的话。每行包含一个形如“A>=3”的名次判断,即一个大写字母+关系运算符+一个数字,不包含空格。大写字母A ~ E,关系运算<、<=、=、>=、>、!=,数字1~5。注意:等于是“=”不是“==”!
输出格式
可能有多解,请按照字典序输出排名序列,每个解一行。最后一行输出解的数量
样例输入
A=2
D=5
E>3
A>2
B!=1
样例输出
ACDEB
AECBD
BADCE
BCADE
BDACE
CEADB
CEBDA
7
解题思路
题中确定为五个人的名词排序,可以先生成所有的排序可能,再根据相应位置上的每个人说的话来判断此排序是否符合条件。
程序实现
import java.util.ArrayList;
import java.util.Scanner;
public class LogicalProblem {
//定义五个人,方便递归输出所有排序可能
public static char[] charAr={'A','B','C','D','E'};
//储存符合条件的排序
public static ArrayList<ArrayList<Character>> list=new ArrayList<>();
//五个人说的五句话
public static String[] JudgeAr=new String[5];
public static void main(String[] args){
Scanner in=new Scanner(System.in);
for(int i=0;i<5;i++){
String line=in.nextLine();
JudgeAr[i]=line;
}
list.add(new ArrayList<>());
boolean[] Mark=new boolean[5];
//找出所有的排序方式并储存在list中
StringGeneration(Mark,0);
//递归后最后一条为空,需要删除
list.remove(list.size()-1);
//输出结果
for(ArrayList<Character> li:list){
for(Character ch:li){
System.out.print(ch);
}
System.out.println();
}
System.out.print(list.size());
}
/**
* 递归生成所有排序可能,并将符合条件的可能保存到{@param list}中
* @param Mark 标记那些人已经处于排序队列中
* @param length 当前排序队列中的人数
*/
public static void StringGeneration(boolean[] Mark,int length){
if(length==5){
//判断当前排序队列是否符合要求,符合要求的保存在list中!!
if(Judge(list.get(list.size()-1))){
ArrayList<Character> newlist=(ArrayList<Character>)(list.get(list.size()-1).clone());
list.add(newlist);
}
return;
}
for(int i=0;i<5;i++){
if(!Mark[i]){
list.get(list.size()-1).add(charAr[i]);
Mark[i]=true;
StringGeneration(Mark,length+1);
list.get(list.size()-1).remove(length);
Mark[i]=false;
}
}
return;
}
/**
* 判断当前名次排序是否符合条件
* @param charList 当前名次排序
* @return 符合 return true; 不符合 return false
*/
public static boolean Judge(ArrayList<Character> charList){
int[] charLoca=new int[5];
for(int i=0;i<5;i++){
int Loca=charList.get(i)-'A';
charLoca[Loca]=i;
}
for(int i=0;i<5;i++){
int Loca=charList.get(i)-'A';
ArrayList<Integer> Evaluation=getLoca(JudgeAr[Loca]);
int OLoca=JudgeAr[Loca].charAt(0)-'A';
//排第1,3,5位的人说假话,2,4位的人说真话
if(i%2==0){
if(Evaluation.contains(charLoca[OLoca]))
return false;
}else{
if(!Evaluation.contains(charLoca[OLoca]))
return false;
}
}
return true;
}
/**
* 当这句话为真时,话中的对象可能的名次:优化方法:程序运行开始就可以将五句话对应状态状态全部保存,避免重复运算
* @param string 当前这个人说的话
* @return 可能的名次
*/
public static ArrayList<Integer> getLoca(String string){
char[] charAr=string.toCharArray();
ArrayList<Integer> result=new ArrayList<>();
if(charAr.length==4){
int value=charAr[3]-'1';
if(charAr[1]=='!') {
for (int i = 0; i < 5; i++) {
if (i == value) continue;
result.add(i);
}
}else if(charAr[1]=='<'){
for(int i=0;i<=value;i++){
result.add(i);
}
}else{
for(int i=value;i<5;i++){
result.add(i);
}
}
}else{
int value=charAr[2]-'1';
if(charAr[1]=='=') {
result.add(value);
}else if(charAr[1]=='<'){
for(int i=0;i<value;i++){
result.add(i);
}
}else{
for(int i=value+1;i<5;i++){
result.add(i);
}
}
}
return result;
}
}