已知 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; }