以下文字摘自《灵机一动·好玩的数学》:“狼人杀”游戏分为狼人、好人两大阵营。在一局“狼人杀”游戏中,1 号玩家说:“2 号是狼人”,2 号玩家说:“3 号是好人”,3 号玩家说:“4 号是狼人”,4 号玩家说:“5 号是好人”,5 号玩家说:“4 号是好人”。已知这 5 名玩家中有 2 人扮演狼人角色,有 2 人说的不是实话,有狼人撒谎但并不是所有狼人都在撒谎。扮演狼人角色的是哪两号玩家?
本题是这个问题的升级版:已知 N 名玩家中有 2 人扮演狼人角色,有 2 人说的不是实话,有狼人撒谎但并不是所有狼人都在撒谎。要求你找出扮演狼人角色的是哪几号玩家?
输入格式:
输入在第一行中给出一个正整数 N(5≤N≤100)。随后 N 行,第 i 行给出第 i 号玩家说的话(1≤i≤N),即一个玩家编号,用正号表示好人,负号表示狼人。
输出格式:
如果有解,在一行中按递增顺序输出 2 个狼人的编号,其间以空格分隔,行首尾不得有多余空格。如果解不唯一,则输出最小序列解 —— 即对于两个序列 A=a[1],...,a[M] 和 B=b[1],...,b[M],若存在 0≤k<M 使得 a[i]=b[i] (i≤k),且 a[k+1]<b[k+1],则称序列 A 小于序列 B。若无解则输出 No Solution
。
输入样例 1:
5
-2
+3
-4
+5
+4
输出样例 1:
1 4
输入样例 2:
6
+6
+3
+1
-5
-2
+4
输出样例 2(解不唯一):
1 5
输入样例 3:
5
-2
-3
-4
-5
-1
输出样例 3:
No Solution
思路:我这里写了个函数来判断暴力列举出的两个狼人是否成立,注意狼人一真一假说谎所以有两种情况,而最优解问题主要看如何列举,问题不大,写的略微复杂......
1 #include<iostream>
2 #include<cstring>
3 #include<cstdlib>
4 #include<cmath>
5 #include<algorithm>
6 #include<map>
7 #include<set>
8 #include<vector>
9 using namespace std;
10 int N;
11 bool panduan( int i , int j , int speak[] )
12 {
13 int book[101]={0};//初始化都为真
14 book[i]=1;//标记1为假
15 book[j]=0;//标记0为真
16 for(int k=1;k<=N;k++)
17 {
18 if(k!=i&&k!=j)
19 {
20 book[k]=1;//遍历第k个为假
21 //一共两个假
22 }
23 else
24 continue;
25 int flag2=1;
26 for(int q=1;q<=N;q++)
27 {
28 if(book[q]==0)//说的是真的
29 {
30 if(speak[q]>0)//说人
31 {
32 if(speak[q]!=i&&speak[q]!=j)//说对了
33 continue;
34 else if(speak[q]==i||speak[q]==j)//说错了
35 {
36 flag2=0;
37 break;
38 }
39 }
40 else if(speak[q]<0)//说狼
41 {
42 int temp=-speak[q];
43 if(temp==i||temp==j)//说对了
44 continue;
45 else if(temp!=i&&temp!=j)//说错了
46 {
47 flag2=0;
48 break;
49 }
50 }
51 }
52 else if(book[q]==1)//说的是假的
53 {
54 if(speak[q]>0)//说人
55 {
56 if(speak[q]!=i&&speak[q]!=j)//说错了
57 {
58 flag2=0;
59 break;
60 }
61 else if(speak[q]==i||speak[q]==j)//说对了
62 continue;
63 }
64 else if(speak[q]<0)//说狼
65 {
66 int temp=-speak[q];
67 if(temp==i||temp==j)//说错了
68 {
69 flag2=0;
70 break;
71 }
72 else if(temp!=i&&temp!=j)//说对了
73 continue;
74 }
75 }
76 }
77 book[k]=0;
78 if(flag2==0)
79 continue;
80 else if(flag2==1)
81 return true;
82 }
83 return false;
84 }
85 int main()
86 {
87 cin>>N;
88 int speak[101];
89 for(int i=1;i<=N;i++)
90 cin>>speak[i];
91 int flag=1;
92 for(int i=1;i<=N;i++)
93 {
94 for(int j=i+1;j<=N;j++)
95 {
96 //假设i和j是狼人,且i说的是假的
97 //j说的是真的
98 if(panduan(i,j,speak)==true||panduan(j,i,speak)==true)
99 {
100 flag=0;
101 cout<<i<<" "<<j<<endl;
102 return 0;
103 }
104 }
105 }
106 if(flag)
107 cout<<"No Solution"<<endl;
108 return 0;
109 }