xmuoj-假币问题

描述

林克有12枚银币。其中有11枚真币和1枚假币。假币看起来和真币没有区别,但是重量不同。但林克不知道假币比真币轻还是重。

于是他向他朋友约珥借了一架天平,用这架天平称了这些币三次。

如果用天平称两枚硬币,发现天平平衡,说明两枚都是真的。如果用一枚真币与另一枚银币比较,发现它比真币轻或重,说明它是假币。

经过精心的设计,聪明的林克根据这三次称量结果找出假币,并且能够确定假币是轻是重。

如果给你林克的称量数据,你也可以找出假币并且确定假币是轻是重吗?(林克提供的称量数据保证一定能找出假币)。

输入

第一行有一个数字n,表示有n组测试用例。

对于每组测试用例:

输入有三行,每行表示一次称量的结果。林克事先将银币标号为A-L。

每次称量的结果用三个以空格隔开的字符串表示:

天平左边放置的硬币  天平右边放置的硬币  平衡状态。

其中平衡状态用``up'', ``down'', 或 ``even''表示, 分别为右端高、右端低和平衡。天平左右的硬币数总是相等的。

输出

输出哪一个标号的银币是假币,并说明它比真币轻还是重(heavy or light)。

输入样例 1 

1
ABCD EFGH even 
ABCI EFJK up 
ABIJ EFGH even 

输出样例 1

K is the counterfeit coin and it is light. 

整体思路:

由于本题的银币数量是有限且比较少的,我们可以采用枚举法,从A开始假设该枚银币是假的+轻的,代入三个已知的式子,看是否都符合,若全都符合,则假设成立,该枚银币为假的+轻的。若从A找到L后还是没有找到符合三个式子的银币,则说明假银币是重的,这个时候就再从A开始假设该枚银币是假的+重的,终会找到符合式子的银币。

现在我们来想这三个提供的条件要怎么用代码表示。

1.首先要先把输入给解决了。这道题我们不能只盯着它的输入样例去写代码,因为输入还可能是

AGHL BDEC even
JKI ADE up
J K even

或者

ABCDEF GHIJKL up
ABC DEF even
I J down


即不是每一边都是4个银币,不能一次存一行,不好处理,所以必须将每一边的银币都分别存进一个字符串里,然后结果也各自储存起来  == > string left[3], right[3], result[3]

2.先搞一个函数来判断此银币为假的+轻的        bool test(char ch,bool islight)

因为我们假设的是此银币为假,所以

        当result==even,那么此银币不能出现在天平的左右两边(否则就不平衡了),所以如果我们检索到此银币出现在left或者right,就return false;

        当result==top,那么此银币就要出现在右端,所以如果我们在right里面检索不到此银币,return false;

        当result==down,那么此银币就要出现在左端,所以如果我们在left里面检索不到此银币,return false;

3.那当我们枚举完假+轻的情况仍然没有找到,还要重新再写一个函数来判断此银币为假的+重的吗?其实不用,当我们用上面一个函数时传入的是 test(char ch,true),那么把true换成false就可以了。

那么三个判断要怎么改呢?top和down的判断结果是要颠倒一下顺序的。为了方便,我们可以创造2个临时字符串l、r储存left和right。

islight==true时,按照第2步思路写代码,因为用了l和r,就把left变成l,right变成r就可以了;

islight==false(即假设假银币是比较重的)时,把l和r的内容交换一下,这样子当result==top,原本假的应该在左边,交换l和r之后假的应该在右边,这样子下面的判断思路就照第2步一样了。

这样子就将两种islight的情况的判断都归于同一个代码,节省了不少代码量。

下面是参考代码

#include <iostream>
#include <cstring>
std::string left[3], right[3], result[3];

bool test(char ch, bool islight)
{ 
    std::string c;
    c.push_back(ch); 

    int count = 0;
    for (int i = 0; i < 3; i++)
    {
        std::string l = left[i];
        std::string r = right[i];
        if (islight == false)
            swap(l, r); 

        switch (result[i][0])
        {
        case 'e':
        {
            if (l.find(c) != std::string::npos || r.find(c) != std::string::npos)
            { 
                return false;
            }
            break;
        }
        case 'u':
        {
            if (r.find(c) == std::string::npos)
            { 
                return false;
            }
            break;
        }
        case 'd':
        {
            if (l.find(c) == std::string::npos)
            { 
                return false;
            }
            break;
        }
        }
    }
    return true;
}
int main()
{

    int t;
    std::cin >> t;
    while (t--)
    {
        for (int i = 0; i < 3; i++)
        {
            std::cin >> left[i] >> right[i] >> result[i];
        }
       
        for (char ch = 'A'; ch <= 'L'; ch++)
        {
            if (test(ch, true))
            { 
                std::cout << ch << " is the counterfeit coin and it is light. " << std::endl;
                break;
            }
            else if (test(ch, false))
            {
                std::cout << ch << " is the counterfeit coin and it is heavy. " << std::endl;
                break;
            }
        }
    }
    return 0;
}

参考链接Andy讲解

<think>好的,我需要帮助用户查询XMUOJ平台上的英雄排行榜情况。首先,用户的问题是关于英雄排名的,但根据提供的引用内容,似乎XMUOJ平台上的资料主要涉及排序算法、逆序数计算、递归应用以及天平问题,没有直接提到英雄排行榜的信息。 接下来,我应该检查所有相关的引用,确认是否有任何隐藏的线索可能与排行榜相关。例如,引用[1]和[2]讨论了归并排序和逆序数,引用[3]涉及递归算法,引用[4]关于假币问题的非枚举思路。这些内容都与算法问题相关,但和用户询问的英雄排行榜没有直接关联。 由于没有直接的信息,我需要考虑如何基于现有资料给出合理的建议。可能的思路是,英雄排行榜可能基于某种算法竞赛的积分或成绩,而排序算法可能用于排名计算。例如,归并排序或快速排序可能用于处理排行榜数据,但用户可能需要具体的查询方式。 另外,用户可能需要知道如何在XMUOJ平台上查看排行榜,比如是否有特定的命令、页面或功能。由于引用中没有提到这些,可能需要引导用户参考平台的官方文档或联系支持人员。 最后,生成相关问题时应围绕可能的排序方法、排名算法或平台使用指南展开,帮助用户进一步探索。</think>根据XMUOJ平台现有公开资料,平台主要涉及算法训练题而非游戏化排名系统。目前可查询到与排序相关的核心算法实现,例如: 1. 归并排序通过递归分治实现,核心代码段为: ```python mergesort(num, left, mid) mergesort(num, mid+1, right) ``` 该算法时间复杂度为$O(n\log n)$,在计算逆序数时能高效统计跨区间的逆序对[^1][^2] 2. 递归算法在纸片选择问题中的应用: ```python choose(int num[], int len) ``` 通过递归计算全局最优解[^3] 3. 非枚举方法解决假币问题时,需处理三种天平状态判断:`up`、`down`、`even`,通过状态分析缩小问题规模[^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值