HOJ 1022 Spacecraft Malfunction

先看下题目:

It is said that court intrigues started with people lying about other people, and then lying about other people’s lying, and so it went. The intriguers constantly looked for scapegoat who inevitably proved to be someone with the least power, though not always the least morality.

We have faced a similar problem, but this time, in our malfunctioning spacecraft! There are a number of units in the spacecraft. The units are so reliable that it would surprise us very much if more than one unit were faulty. If more than one is faulty, we would lose the probe, so we are sure that exactly one unit is faulty in our spacecraft.

We know that each unit checks exactly two others, and each unit will be checked by at least one other unit. A good unit will give accurate diagnosis of the units it checks. For example, if unit X is good and it says that Y is faulty and Z is good, then, in fact, Y is faulty and Z is good. However, a bad unit is unreliable. So, if unit X is faulty and makes the same statements, then Y may or may not be good, and Z may or may not be good either. Note that a unit cannot check itself.

Now suppose that you have the reports from all units and your duty is to find which unit is indeed faulty.

Input
The first line of the input file contains a single integer t (1 <= t <=10), the number of test cases, followed by the input data for each test case. The first line of each test case contains an integer n (3 <= n <= 100), the number of units, followed by n lines each describing a unit and the result of its checks. The line starts with a positive integer number which shows the identification number of the unit. After the id number, there are two pairs of checked unit id's and check results. A check result is a single character which is either Y or N, showing whether the result of checking is good or faulty respectively. As an example, the fourth line in the Sample Input section shows that unit 16 has checked unit 8 saying it is good, and has checked unit 32 saying it is faulty.

Output
There should be one line per test case containing either the id number of the faulty unit, or the word impossible (with lower-case letters), if it is impossible to find the faulty unit from the input data.

Sample Input

1
5
2 16 Y 32 N
16 8 Y 32 N
32 8 N 4 Y
8 4 Y 2 Y
4 2 Y 16 Y
Sample Output
32
题目可以形象的描述为,一堆人在一起,其中有一个骗子,每个人只能并且必须评论两个人,比如上面的例子,2号说16号说的是真话,32号说的是假话。16号说8号说的是真话,32说的是假话....让你找到这几个人里面的骗子,有可能会找不出来,那就打出impossible。

解题思路:

这是一个搜索问题,首先我们先假定2号说的是真的,那么根据2号的话,16号也是真的,然后8号也是真的,然后4号和2号是真的,然后4号说2号和16号真的,出现一个循环,那么假设验证过程结束,说明2号的话没问题。然后我们假定32说的是真的,那么4号是真的,然后2号是真的,然后2号说32号是假的,这里出现矛盾,说明假设不成立,最后32号是骗子。

这里要注意个问题,如果假定某个人说的是真的,而他说的话是某某是假的,另个某某也是假的,这个人光说哪两个人是骗子,没说哪个人的话是真的。这时候我们就先不处理这个假设,先处理其他假设,如果其他假设都是真的,那么这个假设就是假的。否则他就是真的。如果出现两人以上这样的只说谁是骗子的人,而其余假设都是真的,那么就打出impossible。具体代码如下:

#include <iostream>
#include <cstring>
#include <set>
#define MAX 1000
using namespace std;


bool judge(int **p,int unit[],int flag[],int n,int x,set<int>s)
{
    int i;
    for(i=0;i<n;i++)
    {
        if(p[x][unit[i]]==1)
        {
            if(flag[unit[i]]==0)
            {
                flag[unit[i]]=1;
            }
            else if(flag[unit[i]]==-1)
            {
                return false;
            }
        }
        else if(p[x][unit[i]]==-1)
        {
            if(flag[unit[i]]==0)
            {
                flag[unit[i]]=-1;
            }
            else if(flag[unit[i]]==1)
            {
                return false;
            }
        }
    }
    bool st=true;
    for(i=0;i<n;i++)
    {
        if(p[x][unit[i]]==1)
        {
            if(!s.count(unit[i]))
            {
                s.insert(unit[i]);
                st=st&&judge(p,unit,flag,n,unit[i],s);
            }
        }
    }
    return st;
}


int main()
{
    int t,i,n;
    cin>>t;
    for(i=0;i<t;i++)
    {
        int x,y1,j;
        char y2;
        cin>>n;
        int *q=new int[MAX*MAX];
        memset(q,0,MAX*MAX*sizeof(int));
        int **p=new int*[MAX]; //存储输入
        for(j=0;j<MAX;j++)
        {
            p[j]=q+MAX*j;
        }
        int flag[MAX]={0}; //存储验证假设的过程中,每个人的标志
        int unit[n]; //存储每个人的标号


        for(j=0;j<n;j++)
        {
            cin>>x>>y1>>y2;
            unit[j]=x;
            if(y2=='Y')
            {
                p[x][y1]=1;
            }
            else
            {
                p[x][y1]=-1;
            }
            cin>>y1>>y2;
            if(y2=='Y')
            {
                p[x][y1]=1;
            }
            else
            {
                p[x][y1]=-1;
            }
        }
        int fg=1;
        int xx=-1;
        set<int>s;
        for(j=0;j<n;j++)
        {
            int ii;
            int fgg=1;
            for(ii=0;ii<n;ii++)
            {
                if(p[unit[j]][unit[ii]]==1)
                {
                    fgg=0;
                    break;
                }
            }
            if(fgg)        //全是N的情况
            {
                xx=j;
                continue;
            }
            s.clear();
            memset(flag,0,sizeof(int)*MAX);
            s.insert(unit[j]);
            flag[unit[j]]=1;
            if(!judge(p,unit,flag,n,unit[j],s))
            {
                cout<<unit[j]<<endl;
                fg=0;
                break;
            }
        }
        if(fg)
        {
            if(xx!=-1)
            {
                cout<<unit[xx]<<endl;
            }
            else
            {
                cout<<"impossible"<<endl;
            }
        }
        delete q;
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值