[思维]CodeForces 156B Suspects

题意:
有n个嫌疑犯,现在他们说出情况+a[i]表示说a[i]犯罪了,-a[i]表示说a[i]没有犯罪。其中只有一个是罪犯,并且有且只有m个人说的是真话,问最后谁在说谎,谁在说真话,谁的话又是不确定的。

分析:
刚开始拿到这个题,感觉很难下手,想到如何判定凶手的时候就会觉得很烦,大概是有感情因素在里面吧,不够有条理性。
首先假设有5个人,那么说出的情况可能是-1,+1,-2,+2,-3,+3,-4,+4,-5,+5 那么假设1 是凶手,说真话的人必定是m个。好的,那么这个时候说真话的人是(确定是+1的)+(确定其他是负值)的情况和。如果这个和为m,那么这个人是罪犯,如果罪犯的人数大于一,那么谁不是罪犯依然可以确定,但是如果谁是罪犯那就不确定了。
最后再根据每个人说的和实际情况的对比,如果不一致就是撒谎,一致就是说真话,罪犯大于一的时候罪犯不能确定,其他情况可以确定。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <utility>
#include <stack>
#include <queue>
#include <algorithm>
#define read freopen("q.in","r",stdin)
#define write freopen("output.txt","w",stdout)
#define LL long long
using namespace std;
typedef pair<int, int> pii;
const int inf = 0x7fffffff;
const int maxn = 10005;
const int mod = 1000000007;
int a[maxn],b[maxn],c[maxn],sc[maxn];
int vis[maxn];
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        int i,j;
        memset(sc,0,sizeof(sc));
        memset(vis,0,sizeof(vis));
        memset(b,0,sizeof(b));
        memset(c,0,sizeof(c));
        for(i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            if(a[i]>0)b[a[i]]++;
            else c[-a[i]]++;
        }
        int cnt=0;
        for(i=1;i<=n;i++)sc[i]=sc[i-1]+c[i];
        for(i=1;i<=n;i++)
        {
            if(b[i]+sc[i-1]+sc[n]-sc[i]==m)
            {
                vis[i]=1;
                cnt++;
            }
        }
        for(i=1;i<=n;i++)
        {
            if(a[i]>0 && (vis[a[i]]==0))puts("Lie");
            else if(a[i]<0 && vis[-a[i]]==0)puts("Truth");
            else if(a[i]>0 && (vis[a[i]]==1))
            {
                if(cnt>1)puts("Not defined");
                else puts("Truth");

            }
            else if(a[i]<0 && vis[-a[i]]==1)
            {
                if(cnt>1)puts("Not defined");
                else puts("Lie");
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值