正文

应用全排序算法解决一道逻辑推理题2007-03-03 16:14:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/clever101/23628.html

分享到:

                      朱金灿          全排序算法就是列举一些字符的所有排列顺序的一种算法,比较典型的采用递归法。下面是一种简单的全排序算法。   void Swap(char* a, char* b) {// 交换a和b   char temp;  temp = *a;   *a = *b;   *b = temp; } void Perm(char list[], int k, int m) { //生成list [k:m ]的所有排列方式   int i;   if (k == m) {//输出一个排列方式     for (i = 0; i <= m; i++)       putchar(list[i]);     putchar('\n');   }   else // list[k:m ]有多个排列方式     // 递归地产生这些排列方式     for (i=k; i <= m; i++) {       Swap (&list[k], &list[i]);       Perm (list, k+1, m);       Swap (&list [k], &list [i]);     } } int main(int argc, char *argv[]){ char s[6]="01234"; Perm(s,0,4); return 0;}   算法作者:拉格浪日,来源:燕赵草叶风 2006-7-1   下面我简单地应用这个算法解决一道推理问题。该推理是这样的: 一天晚上,一对已婚夫妇,和他们的儿子女儿在家里发生了一起谋杀案,凶手、帮凶、被害人和目击者分别是家里的人。情况如下: (1)目击者和那个帮凶不是同一性别 (2)年龄最大的和目击者不是同一性别 (3)年龄最轻的和被害人不是同一性别 (4)帮凶比受害者大 (5)父亲是年龄最长者 (6)凶手不是家中最年轻的成员 凶手、帮凶、被害人和目击者分别是谁?   算法的基本思路是:定义两个数组,一个数组表示家庭成员,另一个数组表示他们可能扮演的角色。当找出一种排列方式,然后一个数组对另一个数组赋值,如符合题目条件,则进行输出   代码如下: #include <string.h> #include <iostream.h>   struct Person {     char szName[20];        bool Sex; // true 表示男,false表示女     int age; // 定义年龄      };     void Swap(char* a, char* b) {// 交换a和b     char temp;        temp = *a;     *a = *b;     *b = temp; }   void Perm(char list[],Person Familys[],Person Characters[], int k, int m) {        int i = 0;   if (k == m) {       for (i = 0; i <= m; i++)               {                      Characters[i] =  Familys[(list[i]-48)];                 }               // 假如符合题目条件               if((Characters[1].Sex!=Characters[3].Sex) // 目击者和那个帮凶不是同一性别                      &&(Familys[0].Sex!=Characters[3].Sex) //年龄最大的和目击者不是同一性别                      &&(Familys[3].Sex!=Characters[2].Sex) // 年龄最轻的和被害人不是同一性别                      &&(Characters[1].age>Characters[2].age)// 帮凶比受害者大                      &&(Characters[0].age>20) // 凶手不是家中最年轻的成员                      )               {                      cout<<"murderer:  "<<Characters[0].szName<<endl;                      cout<<"accessary:  "<<Characters[1].szName<<endl;                      cout<<"be murdered:  "<<Characters[2].szName<<endl;                      cout<<"the age of be murdered:  "<<Characters[2].age<<endl;                      cout<<"eyewitness:  "<<Characters[3].szName<<endl;                      cout<<"the age of eyewitness:  "<<Characters[3].age<<endl;                      cout<<endl;               }        }        else        {               // 递归地产生这些排列方式               for (i=k; i <= m; i++)               {                      Swap(&list[k], &list[i]);                      Perm(list, Familys,Characters,k+1, m);                      Swap (&list [k], &list [i]);               }        } }     int main(int argc, char* argv[]) {        // 定义一个家庭数组,Familys[0]为父亲,Familys[1]为母亲,Familys[2]为子女中年龄大的一个,Familys[3]为子女中年龄小的一个     Person Familys[4];        // 初始化数组成员,     strcpy(Familys[0].szName,"Father");     Familys[0].Sex = true;     Familys[0].age = 50;     strcpy(Familys[1].szName,"Mother");     Familys[1].Sex = false;     Familys[1].age = 40;        // 首先假设儿子的年龄比女儿要大        strcpy(Familys[2].szName,"Son");     Familys[2].Sex = true;     Familys[2].age = 30;     strcpy(Familys[3].szName,"Daughter");     Familys[3].Sex = false;     Familys[3].age = 20;     // 定义一个角色数组,Characters[0]为,Characters[1]为帮凶,Characters[2]为被害人,Characters[3]为目击者        Person Characters[4];        char s1[5]="0123";     Perm(s1,Familys,Characters,0,3);     char s2[5]="0123";        // 其次假设儿子的年龄比女儿要小     strcpy(Familys[2].szName,"Daughter");     strcpy(Familys[3].szName,"Son");        Familys[2].Sex = false;     Familys[3].Sex = true;     Perm(s2,Familys,Characters,0,3);        return 0; }   其实在STL的next_permutation泛型算法已经实现了全排序,因此更为方便的做法是直接调用这个算法,代码如下:     #include   <iostream>   #include   <vector>   #include   <string>   #include   <algorithm>   #include   <functional>     using   namespace   std;    class Person { public:    Person();    Person(Person &Other);    bool CompareAge(Person &Other);    bool CompareAge(int nAge);    bool CompareSex(Person &Other);    void operator << (int nIndex);    void operator = (Person &Other);    void Initial(char *pszName,bool bSex,int nAge);    void ChangeAge(int NewAge); private:     char m_szName[20]; bool m_Sex; // true 表示男,false表示女     int  m_Age; // 定义年龄 };   Person::Person() {   }   void Person::Initial(char *pszName,bool bSex,int nAge) {     strcpy(m_szName,pszName);     m_Sex = bSex; m_Age = nAge; }   void  Person::operator =(Person &Other) {     strcpy(m_szName,Other.m_szName);     m_Sex = Other.m_Sex; m_Age = Other.m_Age; }   bool Person::CompareAge(Person &Other) {    if(m_Age>Other.m_Age)    return true;    else return false; }   bool Person::CompareAge(int nAge) { if(m_Age>nAge) return true; else return false; }   bool Person::CompareSex(Person &Other) { if(m_Sex!=Other.m_Sex) return true; else return false; }   void Person::ChangeAge(int NewAge) {     m_Age = NewAge; }   void Person::operator <<(int nIndex) { switch(nIndex) { case 0: cout<<"murderer:  "<<m_szName<<endl; break;     case 1:         cout<<"accessary:  "<<m_szName<<endl; break; case 2:         cout<<"be murdered:  "<<m_szName<<endl; cout<<"the age of be murdered:  "<<m_Age<<endl; break; case 3:         cout<<"eyewitness:  "<<m_szName<<endl; cout<<"the age of eyewitness:  "<<m_Age<<endl; break; default: break; } }     void GetMurderer(Person Familys[]) {     vector<char> s1(4); int i =0; s1[0] = '0'; s1[1] = '1'; s1[2] = '2'; s1[3] = '3';     Person Characters[4];       for (i = 0; i <= 3; i++) { Characters[i] = Familys[(s1[i]-48)];   }         if(Characters[1].CompareSex(Characters[3])// 目击者和那个帮凶不是同一性别 &&(Familys[0].CompareSex(Characters[3]))//年龄最大的和目击者不是同一性别 &&(Familys[3].CompareSex(Characters[2])) // 年龄最轻的和被害人不是同一性别 &&(Characters[1].CompareAge(Characters[2]))// 帮凶比受害者大 &&(Characters[0].CompareAge(20))   // 凶手不是家中最年轻的成员 )   {     Characters[0]<<0;         Characters[1]<<1;         Characters[2]<<2;         Characters[3]<<3; cout<<endl;   }   vector<char>::iterator start;     start   =   s1.begin();  vector<char>::iterator end; end = s1.end();        while  ( next_permutation(start,end))   { for (i = 0; i <= 3; i++) { Characters[i] =  Familys[(s1[i]-48)];   } // 假如符合题目条件     if(Characters[1].CompareSex(Characters[3])// 目击者和那个帮凶不是同一性别 &&(Familys[0].CompareSex(Characters[3]))//年龄最大的和目击者不是同一性别 &&(Familys[3].CompareSex(Characters[2])) // 年龄最轻的和被害人不是同一性别 &&(Characters[1].CompareAge(Characters[2]))// 帮凶比受害者大 &&(Characters[0].CompareAge(20))   // 凶手不是家中最年轻的成员 ) {     Characters[0]<<0;         Characters[1]<<1;         Characters[2]<<2;         Characters[3]<<3; cout<<endl; } } }   int main(int argc, char* argv[]) {   // 定义一个家庭数组,Familys[0]为父亲,Familys[1]为母亲,Familys[2]为子女中年龄大的一个,Familys[3]为子女中年龄小的一个     Person Familys[4];     Familys[0].Initial("Father",true,50);     Familys[1].Initial("Mother",false,40);     Familys[2].Initial("Son",true,30);     Familys[3].Initial("Daughter",false,20);     GetMurderer(Familys); // 交换儿子和女儿     Familys[2].ChangeAge(20);     Familys[3].ChangeAge(30); Person tmpPerson;     tmpPerson = Familys[2];     Familys[2] = Familys[3];     Familys[3] = tmpPerson;     GetMurderer(Familys); return 0; }     编译环境:VC6.0  WinXp sp2   运行结果如下:  

阅读(3699) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册