蓝桥杯 算法训练 谁干的好事?

问题描述

  ABCDE中num个人做了好事,truth个人说真话。
  A说:“我和X中有且只有一个做了好事”
  B说:“C和E中有人做了好事”
  C说:“我和D和A中有人做了好事”
  D说:“B和C都没有做好事”
  E说:“我没有做好事”
  请问有哪些人做了好事?

  多组方案请一行一个输出。

输入格式

  仅一行,先是一个整数num,接着是一个A~E的字符X,最后是一个整数truth。意义见题面。

输出格式

  每行输出一组方案,方案中按 字母序 输出做好事的人的代号(A~E),不要空格隔开。

  如果没有合法方案,输出一行一个0即可。

样例输入

1 E 2

样例输出

0

样例输入

2 E 2

样例输出

BD
BE

数据规模和约定

  规定,1 <= num <= 2。

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
 /*
  * 
  * */
public class Main {
	
	static int[] goodMan = new int[5];//1表示做好事,0表示没做好事(下标分别对应A~E)
	static int[] truthMan = new int[5];//1表示说真话,0表示说假话
	static Set<String> list = new HashSet<String>();//存放最后可能的所有结果
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int num = sc.nextInt();//做好事的人数
		char[] str = sc.next().toCharArray();
		char x = str[0];//x的值(A~E之间的一个字符)
		int truth = sc.nextInt();//说真话的人数
		
		searchGood(0, num, truth, x);//找做好事的人
		outputResult();//输出最后的结果
	}
	
	//1.寻找做好事的人(k:表当前找到做好事的人数;num:表做好事的人数; truth:表说真话的人数; x:表A~E之间的一个字符)
	private static void searchGood(int k,int num,int truth,char x){
		if(k == num){//1.1已找到所有做好事的人
			searchTruth(0, truth, x);//再寻找说真话的人
			return;
		}
		for(int i=0;i<5;i++){//1.2 没有找到所有做好事的人(则逐个进行测试)
			if(goodMan[i] == 0){//当前的人i 没有做过好事
				goodMan[i] = 1;//设置i做过好事,当前做好事的人数为k+1
				searchGood(k+1, num, truth, x);	
				goodMan[i] = 0;//若设置i做过好事不合适,则将其重置为没有做过好事
			}
		}
		
	}
	
	//2.寻找说真话的人(k:表当前找到说真话的人数;truth:表说真话的人数;x:表A~E之间的一个字符)
	private static void searchTruth(int k, int truth, char x) {
		if(k == truth){//2.1 已找到所有说真话的人
			if(judge(x)){//如果查找的结果没有矛盾,将其加入到结果集中
				addResult();
			}
			return;
		}
		
		for(int i=0;i<5;i++){//2.2 没有找到所有说真话的人
			if(truthMan[i] == 0){//将i设置为说真话的人,当前说真话的人数为k+1
				truthMan[i]=1;
				searchTruth(k+1, truth, x);//继续找说真话的人
				truthMan[i]=0;//如果测试i说真话不合理,则设置为0
			}
		}
		
	}
	
	//3.判断x是否合理(即当取x时,A、B、C、D、E说真话和说假话 都没有矛盾)
	private static boolean judge(char x) {
		boolean A = (goodMan[0]^goodMan[x-'A']) == truthMan[0];//如果是true,则说明没有矛盾(A说假话和真话都没有矛盾)
		boolean B = (goodMan[2]+goodMan[4]>=1) == (truthMan[1] == 1);
		boolean C = (goodMan[0]+goodMan[2]+goodMan[3]>=1) == (truthMan[2]==1);
		boolean D = (goodMan[1]+goodMan[2]==0)==(truthMan[3]==1);
		boolean E = (goodMan[4]^truthMan[4]) == 1;
		return A && B && C && D && E;
	}
	
	//4.将最终结果加入到结果集中
	private static void addResult() {
		StringBuilder builder = new StringBuilder();
		for(int i=0;i<5;i++){
			if(goodMan[i]==1){//是好人,添加到bulider
				builder.append((char)('A'+i));
			}
		}
		list.add(builder.toString());//将可能的结果存放在list集合中
	}
	
	//5.输出最后结果
	private static void outputResult(){
		if(list.size()==0){
			System.out.println("0");
			return;
		}
		for(String s:list){
			System.out.println(s);
		}
	}
	
	
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值