FZU-2202-犯罪嫌疑人 -10.1训练赛

来源:互联网 发布:淘宝 宝贝分类 编辑:程序博客网 时间:2024/04/29 03:16

PS:我看的别人的博客理解的,比赛的时候没弄出来

PS:转载链接

存在犯罪嫌疑人,当他是实际犯罪者的时候,恰好有且仅有M句话是真话。

那么,如果我们假定一个人是犯罪嫌疑人,有几句话是真话呢?

假设有A句是说xxx是犯罪者的句式,B句是说xxx不是犯罪者的句式。

那么当某人X为犯罪嫌疑人的时候,

真话句数=说X为犯罪者的数量+(B-说X不是犯罪者的数量)//非常自然对吧

然后我们可以得知,哪些人可能是犯罪者了。

如果只有1个人,那么每个人说的话的真假是直接被确定了,毫无疑问。

如果有多个人,

  • 如果某人说的是xxx是犯罪者的句式,如果xxx可能为犯罪者,则他的话可真可假;如果xxx不可能是犯罪者,那他说的一定是假话。
  • 如果某人说的是xxx不是犯罪者的句式,如果xxx可能为犯罪者,则他的话可真可假;如果xxx不可能是犯罪者,那他说的一定是真话。

所以O(n)统计每个人被指认多少次+每个人被排除嫌疑多少次,O(n)来判断每个人是不是可能是犯罪嫌疑人。最后O(n)推断每句话的真假,没了。

#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#include <limits.h>#include <math.h>using namespace std;const int maxn = 1e5+10;int ls[maxn];///记录每个人说的信息int vis[maxn];///记录人是不是可能为犯罪int va[maxn], vb[maxn];///va记录说第i个人犯罪的个数,vb是说第i个人没有犯罪的人数int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n, m;        scanf("%d%d",&n,&m);        fill(vis,vis+n+1,0);///fill 相当于memeset,但是memsest去清0和-1很好,清其他用fill比较好        fill(va,va+n+1,0);///memset(va,0,(n+1)*sizeof(int);        fill(vb,vb+n+1,0);        int cat = 0, cbt = 0;///cat 是说犯罪的人数,cbt是说没犯罪的人数        for(int i = 1; i <= n; i++)        {            scanf("%d",&ls[i]);            if(ls[i] > 0)            {                cat++;                va[ls[i]]++;            }            else            {                cbt++;                vb[-ls[i]]++;            }        }        int ant = 0;        for(int i = 1; i <= n; i++)        {            int tmp = va[i] + (cbt-vb[i]);///说第i个犯罪人的个数加上说其他人没犯罪的人数            if(tmp == m)///如果恰好等于m的话,说明该人可能犯罪啊            {                ant++;                vis[i] = 1;            }        }        if(ant == 1)///找到一个可能的犯罪的        {               for(int  i = 1; i <= n; i++)               {                   if(ls[i] > 0)                   {                       if(vis[ls[i]])///与该人的说法相同                       {                           puts("Truth");                       }                       else                          puts("Lie");                   }                   else                   {                       if(vis[-ls[i]])///和该人的说法相反                       {                           puts("Lie");                       }                       else                       {                           puts("Truth");                       }                   }               }        }        else///多个人可能是犯罪的        {            for(int i = 1; i <= n; i++)            {                if(ls[i] > 0)                {                    if(vis[ls[i]])///该人说他的判断的人犯罪了,没法判断,因为有多个可能的人选                    {                        puts("Not defined");                    }                    else///可以清楚的知道该人不是可能的犯罪的,他就说谎了                        puts("Lie");                }                else                {                    if(vis[-ls[i]])///该人说他的判断的人没有犯罪了,没法判断,因为有多个可能的人选                    {                        puts("Not defined");                    }                    else///可以清楚的知道该人不是可能的犯罪的,所以该人说的对                        puts("Truth");                }            }        }    }    return 0;}


0 0
原创粉丝点击