诚实的人与说谎的人(Java)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/l870358133/article/details/102090436

在一个岛上有两种人:诚实的人和说谎的人。诚实的人总是说真话,而说谎的人总是说假话。已知岛上总共有N个人,假设你是一个逻辑学家,你可以问岛上的每一个人同样的问题: 岛上有多少诚实的人? 岛上的第i个人回答: 诚实的人数介于ai和bi之间。 请你据此判断岛上每一个人是诚实的人还是说谎的人。

输入格式:

输入包括多组测试数据。每组测试数据的第一行包含岛上总的人数N(0<=N<=100),接下来是N行,每行包括诚实人数的下界ai(0<=ai<=N)和诚实人数的上界bi(0<=bi<=N)。N为0表示输入结束。

输出格式:

对每组测试数据,输出包含一个N位的二进制整数。该二进制整数的第i位为1表示第i个人是诚实的人,为0表示第i个人是说谎的人。如果一组测试数据的解不唯一,输出的二进制整数要求是所有可能解中最小的一个数。如果一组测试数据没有解,输出–1。

输入样例:

1
0 1
4
1 4
2 4
3 4
4 4
3
1 2
0 0
1 3
1
0 0
0

输出样例:

1
0000
101
–1


import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		while(n!=0) {
			int[][] tf = new int[n][2];
			for(int i=0;i<n;i++) {
				tf[i][0] = sc.nextInt();
				tf[i][1] = sc.nextInt();
			}
			int min = 0;					//确定每组最小
			String minstr = "";				//确定每组最小排列
			for(int i=0;i<=n;i++) {			//i为说真话的人数
				String str = "";			//存储每个人说的是真话还是假话
				int count = 0;				//判断人数是否匹配
				for(int j=0;j<n;j++) {
					if(tf[j][0]<=i && i<=tf[j][1]) {	//说明当前第j个人说了真话
						str += "1";
						count++;
						if(count > i)		//当前计数说真话的人数大于i
							break;
					}
					else {
						str += "0";
					}
				}
				if(count==i) {				//说明至少存在一组解
					int num = Integer.parseInt(str, 2);
					if(minstr.length()==0 || min>num) {
						min = num;
						minstr = str;
					}
				}
			}
			if(minstr.length() != 0) {
				System.out.println(minstr);
			}
			else
				System.out.println("-1");
			n = sc.nextInt();
		}
	}
}

这个题记得之前就看到过,但是当时不会做。这次倒是有思路了,但是未能拿到全分。我的思路是,把每个人的回答全部录入之后,从没有说实话的到全部说的实话对所有人的话进行判断,如果说实话的人数和每个人说的是真话的人数对上了,那证明当前的说实话的人数队列符合要求,如果有多组那么加一个判断,只保存相应数字最小的那一组。说实话效率有点低,但是这是我想到的最好的方法了,代码里面存在问题,提交只对了一半,实在看不出来了,发上来看看哪位大佬可以帮忙找一下错误,感谢!


修正后代码如下

import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		while(n!=0) {
			int[][] tf = new int[n][2];		//存每个人说的范围
			for(int i=0;i<n;i++) {
				tf[i][0] = sc.nextInt();
				tf[i][1] = sc.nextInt();
			}
			int min = -1;					//确定最小的数
			String minstr="-1";				//确定最小值的队列
			for(int i=0;i<=n;i++) {			//i为说真话的人数
				String str = "";			//存储每个人说的是真话还是假话
				int count = 0;				//判断人数是否匹配,有一个说真话的count自加1
				int tmp=0;					//用来记录队列转换的二进制数的大小
				for(int j=0;j<n;j++) {
					if(tf[j][0]<=i && i<=tf[j][1]) {	//说明当前第j个人说了真话
						str+=1;
						tmp=(tmp<<1)+1;
						count++;
						if(count > i)		//当前计数说真话的人数大于i
							break;
					}
					else {
						str+=0;
                        tmp=(tmp<<1)+0;
                    }
				}
				if(count==i) {				//说明至少存在一组解
					if(min>tmp || min==-1) {
						min = tmp;
						minstr = str;
					}
				}
			}
				System.out.println(minstr);
			n = sc.nextInt();
		}
	}
}

错误出现在“可能解中最小的一个数”上,原始代码用Integer.parseInt(str, 2)方法直接将01队列转化成相应二进制数,可能有什么没有考虑到,在改进的代码中用tmp=tmp<<1+(0或1),在其中直接计算01队列对应的二进制数,而不是在最后计算了,结果就正确了,其实还是有些迷惑,等有时间再细细研究。

猜你喜欢

转载自blog.csdn.net/l870358133/article/details/102090436