谁是小偷

某商场发生了一起盗窃案,商场经理将现场的顾客全部滞留,并报案。接到报案后,大侦探急忙赶到现场。他将现场的全部人员从1M编号(包括经理),并询问谁是小偷,一个人最多被询问一次。被询问人员可以回答:***号是小偷、***号不是小偷(***号可能是自己,也可能是不在现场的某个人的编号,由大侦探临时依次序增加编号),也可以不回答。假设最多只有一个小偷。大侦探判断出其中有N个人始终在说假话,而其他的人始终在说真话,于是立即知道了结果。聪明的程序员,您能编程判断出谁是小偷吗?

 

输入(请使用标准输入、输入,不要读写文件)

输入由若干行组成。第一行有三个整数:M是总的人员数、N是始终说假话的人员、P是说话的总次数。第二到第P+1行是回答记录,每行两个数:第一个数是说话人的编号,第二个数或者是0,表示不说话,或者是说话人提到的人员编号或该编号的负数:为正时表示该编号是小偷,为负是表示该编号不是小偷。同一行的数以空格符分隔。其中,1M20N(1NM)P1P100)。

输出(请使用标准输入、输入,不要读写文件)

如果程序能确定谁是小偷,则输出他的编号,如果不止一个结果则输出-1,没有结果时输出0

 

样例输入1

样例输出1

样例输入2

样例输出2

样例输入3

样例输出3

5 2 4

1 3

2 1

3 1

4 -5

 

 

3

5 1 5

1 -1

2 -2

3 -3

4 -4

5 -5

-1

5 3 6

1 2

2 1

3 4

4 2

4 3

5 5

0

 

 

解法1

#include <iostream>

#include <set>

#include <vector>

using namespace std;

void main()

{

       int a = 0; //总人数 

       int b = 0; //说谎的人数

       int c = 0; //说话次数

       int p[100][2];//记录每行的记录  

       cin >>a>>b>>c;

       for ( int i=0 ; i<c; i++)

       {

              int n , m;

              cin>>n>>m;

              p[i][0] = n;

              p[i][1] = m;

       }

       vector<int> thief;

    //依次假定第1-a是小偷

       for ( int j = 1 ; j <=a ; j++ )

       {

              set<int> s;

              for ( int k = 0 ; k < c ; k++)

              {

                     //判断第k条记录是否是谎言

                     if( ( p[k][1] > 0 && p[k][1] != j) || ( p[k][1] < 0 && -p[k][1] == j) )

                     {

                            s.insert(s.begin(),p[k][0]);

                     }

              }

              if (s.size() == b)

              {

                     thief.push_back(j);

              }

       }

       if ( thief.size() == 1) //能确定谁是小偷

       {

              cout<<thief.at(0)<<endl;

       }

       else if ( thief.size() == 0) //没有结果

       {

              cout<<0<<endl;

       }

       else //不止一个结果

       {

              cout<<-1<<endl;

       }

}

 

 

解法2:当年一个朋友写的

解法2

#include <iostream>

#include <vector>

#include <string>

 

using namespace std;

 

class Person

{

public:

       enum { MAX_NUM = 20 };

 

       Person()  { perNum = 0; }

       bool SetNum(int n, int s) 

       {

              if (s > n)

                     return false;

 

              perNum = n;

              isfa = s;

              return true;

       }

 

       bool AddInfo(int , int );         //判断信息是否有效并添加信息,无效返回false

       bool Judge(int );                   //判断小偷是第x个人时是否产生矛盾,产生返回false,否则返回true

       void ShowRes();

private:

       int test(int a, int b);        //a是小偷时,b说的全是真话返回0,全是假话返回1,相矛盾返回-1         

       int perNum;                                //总人数

       int isfa;                                //说假话的人数

       vector<int> per[MAX_NUM+1];

};

 

int main()

{

       int a, b, c;

      

       do

       {

             

              cin >> a;  //总人数

             

              cin >> b;   //说谎的人数

 

              Person p;

              if ( !p.SetNum(a, b) )

              {

                     cout << "输入错误/n/n/n";

                     continue;

              }

 

      

              cin >> c; //说话次数

 

              for (int i=0; i<c; i++)

              {

                     int k, j;

                     cout << ">";

                     cin >> k >> j;

                     p.AddInfo(k, j);

              }

              cout << ">>";

              p.ShowRes();

 

              char ch;

              cout << "是否退出(Y/N):";

              cin >> ch;

              if (ch=='Y' || ch=='y')

                     break;

              cout << endl << endl;

       }while (true);

 

       return 0;

}

void Person::ShowRes()

/*分别假设从1--perNum的人为小偷,通过Judge判断是否满足条件,

通过满足条件的人数目输出相应结果*/

{

       int count = 0;

       int n;

       for (int i=1; i<=perNum; i++)

       {

              if ( Judge(i) )

              {

                     n = i;

                     count++;

              }

       }

 

       if (count == 1)

              cout << n << endl;

       else if (count == 0)

              cout << 0 << endl;

       else

              cout << -1 << endl;

}

 

      

int Person::test(int n, int a)

/*假设第n个人是小偷,判断a是说假话还是真话,说假话返回1,说真话返回0,

说话有矛盾返回-1(说明假设第n个人是小偷有错误)*/

{

       vector<int>::iterator it;

       bool flag;

       bool m = false;

 

       for (it=per[a].begin(); it!=per[a].end(); it++)

       {

              if (*it > 0)

              {           

                     if(*it == n)

                     {

                            if ( !m )

                            {

                                   flag = true;

                                   m = true;

                            }

                            else if (m && !flag)

                                   return -1;

                     }

                     else

                     {

                            if ( !m )

                            {

                                   flag = false;

                                   m = true;

                            }

                            else if (m && flag)

                                   return -1;

                     }

              }

              else if (*it < 0)

              {           

                     if(-1*(*it) != n)

                     {

                            if ( !m )

                            {

                                   flag = true;

                                   m = true;

                            }

                            else if (m && !flag)

                                   return -1;

                     }

                     else

                     {

                            if ( !m )

                            {

                                   flag = false;

                                   m = true;

                            }

                            else if (m && flag)

                                   return -1;

                     }

              }

       }

       return flag?0:1;

}

                    

bool Person::Judge(int n)

/*判断第n个人为小偷时是否满足条件

通过说假话的人数(test得到)isfa比较判断,当有一个说话矛盾时假设不正确

假设不正确返回false,正确返回true*/

{

       int count = 0, k;

 

       for (int i=1; i<=perNum; i++)

       {

              k = test(n, i);

              if (k == -1)

                     return false;

 

              count += k;

       }

       if (count == isfa)

              return true;

       return false;

}

 

bool Person::AddInfo(int n, int in)

/*添加信息(nin是小偷)*/

{

       if (n<=0 || n>perNum)

              return false;

 

       per[n].insert(per[n].end(), in);

       return true;

}

 

 

你可能感兴趣的:(编程,c,iterator)