在一个岛上有两种人:诚实的人和说谎的人。诚实的人总是说真话,而说谎的人总是说假话。已知岛上总共有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队列对应的二进制数,而不是在最后计算了,结果就正确了,其实还是有些迷惑,等有时间再细细研究。