1089 狼人殺-簡單版 (20 分)

  • 2019 年 11 月 8 日
  • 筆記

版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。

本文鏈接:https://blog.csdn.net/shiliang97/article/details/99648656

1089 狼人殺-簡單版 (20 分)

以下文字摘自《靈機一動·好玩的數學》:「狼人殺」遊戲分為狼人、好人兩大陣營。在一局「狼人殺」遊戲中,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

先放答案

#include<iostream>  #include<vector>  using namespace std;  int main(){  	int n;  	int v[105];  	int a[105];  	cin>>n;  	for(int i=1;i<=n;i++){  	cin>>v[i];  	}  	for(int i=1;i<=n;i++){  		for(int j=i+1;j<=n;j++){  			for(int l=1;l<=n;l++){  				a[l]=1;  			}    		vector<int>lie;  		a[i]=-1;  		a[j]=-1;  		for(int k=1;k<=n;k++){  			//cout<<v[k]<<" "<<a[abs(v[k])]<<"*";  			if(v[k]*a[abs(v[k])]<0){  			lie.push_back(k);  			}  		//printf("%2d",a[k]);  		}  		//cout<<" "<<lie.size()<<endl;  		if(lie.size()==2&&a[lie[0]]*a[lie[1]]==-1){  			cout<<i<<" "<<j;  			return 0;  		}  	}  	}  	cout << "No Solution";  	return 0;  } 

再放柳神的超級簡潔的答案(我抄的她的)

水平高下立刻見

#include <iostream>  #include <vector>  #include <cmath>  using namespace std;  int main() {      int n;      cin >> n;      vector<int> v(n+1);      for (int i = 1; i <= n; i++) cin >> v[i];      for (int i = 1; i <= n; i++) {          for (int j = i + 1; j <= n; j++) {              vector<int> lie, a(n + 1, 1);              a[i] = a[j] = -1;              for (int k = 1; k <= n; k++)                  if (v[k] * a[abs(v[k])] < 0) lie.push_back(k);              if (lie.size() == 2 && a[lie[0]] + a[lie[1]] == 0) {                  cout << i << " " << j;                  return 0;              }          }      }      cout << "No Solution";      return 0;  }

一道20分的簡單題,活生生的寫了1小時20分鐘

這是我的做題流程

直接按照題目說的,直接暴力編程,能過一部分測試點,那兒不會也查不出來,因為太亂了

#include<iostream>  #include<algorithm>  using namespace std;  int sum[105];  int person[105];  struct zong{  	int a;  	int b;  };  zong z[1000];  int cou=0;  int cmp(zong z1,zong z2){  	if(z1.a==z2.a){  		return z1.b<z2.b;  	}else{  		return z1.a<z2.a;  	}  }  int main(){  	int n;  	cin>>n;  	for(int i=1;i<=n;i++){  		cin>>sum[i];  	}//存入信息  	for(int i=1;i<=n;i++){  		//撒謊狼人循環  		for(int k=1;k<=n;k++){//撒謊好人循環  			if(k==i){  				continue;  			}  			//判斷能否出答案  			for(int l=1;l<=n;l++){  				//清零  				person[l]=0;  			}  			for(int l=1;l<=n;l++){    				//存入推理信息  				if(l==i||l==k){  					int s=sum[l];//撒謊的人說的  					if(s<0){  						//撒謊的說是壞人,就是好人  						if(person[-s]==-1 ){  							person[i]=1;  						}  						person[-s]=1;  					} else{  						// 撒謊的說是好人,就是壞人  						if(person[s]==1 ){  							person[i]=1;  						}  						person[s]=-1;  					}    				}  				else{    					int s=sum[l];//撒謊的人說的  					if(s<0){  						if(person[-s]==1 ){  							person[i]=1;  						}  						//說是壞人,就是壞人  						person[-s]=-1;  					} else{  						// 說是好人,就是好人  						if(person[s]==-1 ){  							person[i]=1;  						}  						person[s]=1;  					}  				}      			}  			if(person[i]==0){  				person[i]=-1;  			}  			if(person[i]!=-1){  				continue;  			}  			//推一下,有沒有答案  				int huai[100];  				int huaicount=0;  				for(int l=1;l<=n;l++){  					//printf("%2d ",person[l]);  					if(person[l]==-1){  						huai[huaicount++]=l;  					}  				}  				//cout<<endl;  				if(huaicount==2){  					//cout<<"判斷"<<huai[0]<<" "<<huai[1]<<"sahuang"<<i<<" "<<k<<endl;  					if(huai[0]!=k&&huai[1]!=k){  						if(huai[0]==i||huai[1]==i){  							//cout<<huai[0]<<" "<<huai[1]<<endl;  							z[cou].a=huai[0];  							z[cou++].b=huai[1];    							//return 0;  						}  					}  				}  		}  	}  	sort(z+0,z+cou,cmp);  	if(cou>0){  		cout<<z[0].a<<" "<<z[0].b;  		return 0;  	}  	cout<<"No Solution";  	return 0;  } 

緊接着搜索柳神的代碼

學習一波自己敲還是錯誤百出….人家STL容器選的就是很適合。

柳神是直接遍歷兩個狼人去試探,我是直接遍歷兩個說謊的人去試探。

問題主要(我已經發現的)出在了答案不唯一的輸出上,

如果解不唯一,則輸出最小序列解

柳神的方法,直接從最小的1,2 開始算只要出現解,就是最小解

而我的方法,使用1 ,2 說謊開始算的,要輸出最小解,就需要遍歷所有的答案,最後還要排序啥的,一堆事情,最後才能輸出最小解。

說明還是做得題少,多做,多思考。爭取下一道做上來。

#include <iostream>  #include <vector>  #include <cmath>  using namespace std;  int main() {      int n;      cin >> n;      vector<int> v(n+1);      for (int i = 1; i <= n; i++) cin >> v[i];//存進來  	for (int i = 1; i <= n; i++) {          for (int j = i + 1; j <= n; j++) {          	vector<int> lie, a(n + 1, 1);//默認都是好人              a[i] = a[j] = -1;//兩個壞人              for (int k = 1; k <= n; k++){                    if (v[k] * a[abs(v[k])] < 0) lie.push_back(k);//v[k]是k說的話,a[abs (v[k])],是哪個人的真是情況實物與存的信息不符,存進謊話里          }    			if (lie.size() == 2 && a[lie[0]] + a[lie[1]] == 0) {//謊話的1.兩個人,2.一個好人一個壞人                  cout <<i<<" "<< j;//輸出壞人                  return 0;              }          }      }      cout << "No Solution";      return 0;  }