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