[PAT]1148 Werewolf - Simple Version(20 分)

这是2018年9月8日PAT考试甲级第一题,当时看完题目什么思路也没有,就直接跳过做第二题(因为我看第二题还好多人做出来了)。最后终于有了思路,但是读题题意理解错了,原文是"at least one but not all the werewolves were lying"即只有一个狼人说谎,自己当时理解了,要么只有一个狼人说谎,要么没狼人说谎,最后提交只过了一个"No Solution"样例,捡了2分。最后成绩也很不理想,只解除二、三两道题。代码以后还得练啊!

另外听同学说这道题是顶级里面的原题,在顶级里35分,怎么到甲级就20分了呢?因为是原题目么?要是多做点题也许可以解出来呢,反正,这次考试算是试水吧,12月份再战!!!

题目


Werewolf(狼人杀) is a game in which the players are partitioned into two parties: the werewolves and the human beings. Suppose that in a game,

  • player #1 said: "Player #2 is a werewolf.";
  • player #2 said: "Player #3 is a human.";
  • player #3 said: "Player #4 is a werewolf.";
  • player #4 said: "Player #5 is a human."; and
  • player #5 said: "Player #4 is a human.".

Given that there were 2 werewolves among them, at least one but not all the werewolves were lying, and there were exactly 2 liars. Can you point out the werewolves?

Now you are asked to solve a harder version of this problem: given that there were N players, with 2 werewolves among them, at least one but not all the werewolves were lying, and there were exactly 2 liars. You are supposed to point out the werewolves.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (5≤N≤100). Then N lines follow and the i-th line gives the statement of the i-th player (1≤i≤N), which is represented by the index of the player with a positive sign for a human and a negative sign for a werewolf.

Output Specification:

If a solution exists, print in a line in ascending order the indices of the two werewolves. The numbers must be separated by exactly one space with no extra spaces at the beginning or the end of the line. If there are more than one solution, you must output the smallest solution sequence -- that is, for two sequences A=a[1],...,a[M] and B=b[1],...,b[M], if there exists 0≤k<M such that a[i]=b[i] (i≤k) and a[k+1]<b[k+1], then A is said to be smaller than B. In case there is no solution, simply print No Solution.

翻译


大意是,狼人杀游戏,共n名玩家,其中两名狼,其他都是人。每名玩家判断其他某位玩家是狼还是人。其中一个狼,一个人说的假话,其他说的都是真话,让你判断n名玩家中哪两位是狼人。如果没有解输出No Solution,如果有多个解输出最小序列(这个最小序列我也没怎么看懂, 应该就是序号小的解)。

输入样例


5
-2
+3
-4
+5
+4

 输出样例


1 4

 样例分析


一共5名玩家,1号认为2号是狼,2号认为3号是人,3号认为4号是狼,4号认为5号是人,5号认为4号是人。

当1号4号为狼时, 满足:5位玩家中两人说谎,其中一个是狼,一个是人。

思路


暴力解法。分别假设第i,j号玩家是狼,那么其他玩家都是人,再逐次判断每名玩家说谎与否,若满足:共两名玩家说谎,一名是狼一名是人,则记录i,j即为一组解。不满足则继续往下判断假设i,j+1为狼。

代码


#include <iostream>
#include <vector>
#include <math.h>

using namespace std;
int said[105];            //玩家的发言
int state[105];           //各玩家身份,1代表是人,0代表是狼
vector<int> ans;
int n;

//判断第player号玩家是否说谎
bool isLiar(int player){
    int num = said[player]>0?said[player] : said[player]*-1;
    int f = said[player]>0 ? 1 : 0;


    if(f == state[num])
        return false;
    else
        return true;
}


//判断假设 wolf_1,wolf_2为狼人的话是否满足题目要求
bool satisfy(int wolf_1, int wolf_2){
    for(int i=1; i<=n; i++){
        if(i==wolf_1 || i == wolf_2){
            state[i] = 0;
        }else{
            state[i] = 1;
        }
    }

    int liars = 0;

    if(isLiar(wolf_1) && isLiar(wolf_2) || (!isLiar(wolf_1) && !isLiar(wolf_2)))
        return false;

    for(int i=1; i<=n; i++){
        if(isLiar(i)){
            liars ++;
        }

        if(liars > 2){
            return false;
        }
    }

    if(liars == 2)
        return true;
}


int main()
{
    cin>>n;

    for(int i=1; i<=n; i++){
        cin>>said[i];
    }
    int f = 0;


    for(int i=1; i<=n-1; i++){
        for(int j=i+1; j<=n; j++){
            if(satisfy(i, j)){
                ans.push_back(i);
                ans.push_back(j);
                f = 1;
                break;        //若有解,立马跳出循环(因为题目要求只输出一组序列最小的解)
            }
        }

        if(f == 1)
            break;
    }



    if(ans.size() == 0){
        cout<<"No Solution"<<endl;
    }else{
        cout<<ans[0]<<" "<<ans[1]<<endl;
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值