已知 N 名玩家中有 2 人扮演狼人角色,有 2 人说的不是实话,有狼人撒谎但并非全部狼人都在撒谎。要求你找出扮演狼人角色的是哪几号玩家,若是有解,在一行中按递增顺序输出 2 个狼人的编号;若是解不惟一,则输出最小序列解;若无解则输出 No Solution.算法
题意不太好理解,此题没有考察任何算法技巧,是一个模拟题,重点在于根据给定的信息假设一个肯定条件,在搜索过程当中,出现同时符合第二个条件的就是解,具体来讲就是,题目给定了2个肯定的条件,第一个就是有且仅有2个狼人,第二个就是有2人说谎,一个是狼人,一个是平民。题目既然要求给出狼人的编号,那么搜索的全体空间就是全部人,因为狼人有2个,因此得使用双重循环搜索全部狼人,分别使用i和j表明2个狼人的编号(i<=j)。既然如今肯定了狼人的编号,就说明第一个肯定条件已经使用,如今就是须要知道怎么知道一我的有说谎了,其实也很简单,每次搜索的时候,咱们给全部人一个初始状态,均为1,表示平民,让i和j为-1表示狼人,若是有一我的k说的话指定的那我的的状态a[k]与其如今自己的状态不一致就说明k在说谎。具体的作法就是,使用state初始化为1,state[i] = state[j] = -1;
遍历每个人的编号,只要a[k]*state[abs(a[k])]<0
(a[k]为k所说的那我的的身份),就说明k在说谎,记录下来,添加进liars中,只要liars.size()==2&&state[liars[0]]+state[liars[1]]==0
,说明如今找到一个解,因为是从前日后搜索获得的结果,编号必定是最小的,直接退出循环。spa
考场上要是碰见这个题,心态可能得崩溃。
#include<cstdio> #include<vector> #include<algorithm> using namespace std; int main(){ int N; scanf("%d",&N); int a[N+1]; for (int i = 1; i <= N; ++i) { scanf("%d",&a[i]); } // 暴力搜索,遍历全部的狼人,找到2个说谎的人,一人是平民,一人是狼人 for (int i = 1; i <= N; ++i) { for (int j = i+1; j <= N; ++j) { // 首先初始化每个人的状态,假设都是平民 int state[N+1]; fill(state,state+N+1,1); //(i,j)是一对狼人 state[i] = state[j] = -1; // 只要当前人说的话与那我的的身份不符合,说明在说谎 vector<int> liars; state[i] = state[j] = -1; for (int k = 1; k <= N; ++k) { if(a[k]*state[abs(a[k])]<0){ //k在说谎,记录下来 liars.push_back(k); } } if(liars.size()==2&&state[liars[0]]+state[liars[1]]==0){ // 找到一组解 printf("%d %d",i,j); return 0; } } } printf("No Solution"); return 0; }