今天刷了一道PTA的题,该题的意思是:已知N人的狼人杀游戏中,有2人扮演狼人的角色,有2人说的不是实话,有狼人撒谎,但并不是所有的狼人都撒谎。请找出扮演狼人的角色?
已知输入格式为:第一行输入一个正整数N,表示有几名玩家,5≤N≤100;随后的N行,第i行给出第i名玩家说的话。如第一行:+2,表示第一名玩家说,第二人是好人 1≤i≤N
输入格式要求:如果有解,在一行中按照递增顺序输出2个两人的编号,其间以空格分隔,行首尾不得有多余的空格;如果解不唯一,则输出最小序列解——即对于两个序列,A{a1,a2,.....,am}和B{b1,b2,.....,bm}若存在0≤k≤m使得
ai=bi(i≤k)且a(k+1)<b(k+1),则称序列A小于序列B;若无解,则输出no solution
解法是:①首先获取系统输入,我这里是用数组保存的;②然后遍历,我这里是O(N^3)的复杂度。并且采用两个辅助变量,分别是wolf和lie两个数组。其中lie保存的是谁在撒谎。wolf保存的是狼人信息,值为1时是好人,为-1时是狼人;③前两个n循环,得到两个变量ij,假设ij是狼人,那么wolf[i/j]=-1;那么问题就变成了判断谁在撒谎。因为从题干中可以看出,有两个人在撒谎,一人是好人一人是狼人。
那么如何判断谁在撒谎呢,因为已经指导了狼人信息,那么就可以看每个人说的话,和他确切身份是否符合。具体地代码如下:
import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class WerewolfKillingGame_1089 { public static int[] solution(){ //获取系统输入 Scanner scanner=new Scanner(System.in); int n=scanner.nextInt(); int i=0; int [] h=new int[n]; while (i<n){ h[i]=scanner.nextInt(); i++; } int[] result=new int[2]; //总结来看,该算法即三次遍历输入数组,首先假设jk为狼人,然后去看谁在撒谎 //因为只有两人撒谎,并且有一个是好人另一个是狼人 //然后问题就转化成了,在假设已知两个狼人的基础上,如何判断谁在撒谎 for (int j = 0; j <n-1 ; j++) { for (int k = j+1; k <n ; k++) { List<Integer> lie=new ArrayList<>();//存储的是某个人说的话是真还是假 int[] wolf=new int[n];//1表示好人 for (int ii = 0; ii <n ; ii++) { wolf[ii]=1; } wolf[j]=-1; wolf[k]=-1; for (int l = 0; l <n ; l++) { //第l个人发言,说h[l]个人是好人还是狼人。因为已经假定好了已知的两个狼人,因此可以判断乘积来确定是否在撒谎 if (h[l]*wolf[Math.abs(h[l])-1]<0) { lie.add(l); } } //针对每一组情况,判断是否已经找到了答案 if (lie.size()==2 && wolf[lie.get(0)]+wolf[lie.get(1)]==0) { System.out.println((j+1)+" "+(k+1)); result[0]=j; result[1]=k; return result; } } } System.out.println("No Solution!"); return null; } }