POJ 1029--False coin

题意

题目意思是讲,有若干个硬币,其中可能存在一个质量有误的。现在通过许多次比较来确定哪个的质量不同于其他硬币。

分析

每一次比较的时候,只要不是“=”,显然两边的任何一个硬币都有嫌疑。因此,在每一次不是“=”的时候,为所有嫌疑币施加一个嫌疑值。我们约定让天平较低一方的所有硬币,嫌疑值-1,让较高的+1。当出现“=”的时候,重置两侧硬币的嫌疑值为0(这些硬币质量肯定正确)。假定最后只有一个硬币的嫌疑值不为0,那么显然这个币质量不同于其他,如果有多个非0,那么便是绝对值较大的。

至于理由,其实也简单。假定有异常硬币重于其他的硬币,那么它的嫌疑值便会一直增加。而其他硬币跟这枚异常币在一个托盘的时候,嫌疑值会增加,但在对面托盘的时候,嫌疑值会降低,那么最后它们的嫌疑值的绝对值便小于异常币。最后如果出现多个最大绝对值,说明有一枚币跟异常币一直在一个托盘,或者一直在对面托盘,这样显然在题目要求下无解。异常币要么不存在,要么只会有一个,所以此法可行。

代码如下:
Memory: 124K Time: 16MS Length: 79LINES

#include<cstdlib>
#include<cstdio>
int ArrInt[1001] = {};
bool ArrBl[1001] = {};
int num[1000] = {};
int N = 0;
int K = 0;
int Pi = 0;
char cmp;
int sign = 0;
int main()
{
    scanf("%d%d", &N, &K);
    for (int i = 0; i < K; ++i)
    {
        scanf("%d", &Pi);
        for (int j = 0; j < Pi * 2; ++j)    scanf("%d", &num[j]);
        getchar();
        scanf("%c", &cmp);
        if (cmp == '=')
            for (int k = 0; k < Pi; ++k)
                ArrBl[num[k]] = ArrBl[num[k + Pi]] = true;
        else if (cmp == '<')
        {
            ++sign;
            for (int k = 0; k < Pi; ++k)
            {
                if (!ArrBl[num[k]])         --ArrInt[num[k]];
                if (!ArrBl[num[k + Pi]])        ++ArrInt[num[k + Pi]];
            }
        }
        else
        {
            ++sign;
            for (int k = 0; k < Pi; ++k)
            {
                if (!ArrBl[num[k]])             ++ArrInt[num[k]];
                if (!ArrBl[num[k + Pi]])            --ArrInt[num[k + Pi]];
            }
        }
    }
    int key = 0;
    int key2 = 0;
    int count = 0;
    int first = 0;
    int seconed = 0;
    for (int i = 1; i <= N; ++i)
    {
        if (sign == 0)
        {
            if (!ArrBl[i])
            {
                if (++count > 1)        break;
                key = i;
            }
        }
        else
        {
            if (!ArrBl[i] && ArrInt[i] != 0)
            {
                if (abs(ArrInt[i]) >= seconed)
                {
                    first = seconed;
                    seconed = abs(ArrInt[i]);
                    key2 = i;
                }
                ++count;
                key = i;
            }
        }
    }
    if (count == 1) printf("%d\n", key);
    else
    {
        if (sign == 0 || first == seconed)      printf("%d\n", 0);
        else        printf("%d\n", key2);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值