OpenJudge NOI 2.1 15:Counterfeit Dollar

【题目链接】

OpenJudge NOI 2.1 15:Counterfeit Dollar

【题目考点】

1. 枚举

【题目翻译】

题目

假币

描述

莎莉琼斯有12枚航记银元,但是,只有其中的11个是真正的银元,有1枚是伪造的假币,尽管它的颜色和形状大小让它无法与真正的银元区分开来。这个假币与其他硬币的重量不同,但莎莉不知道它与其他硬币相比是更重还是更轻。

幸运的是,莎莉有一个朋友借给了她一个十分精确的天平,这个朋友给了莎莉三次称重的机会来找出那个假币。例如,如果莎莉称两枚硬币且天平平衡,那么她就知道这两枚硬币是真的。现在,如果莎莉将其中一枚真硬币与第三个硬币称重,天平不平衡,那么她就知道第三枚硬币是假币,并且她还能通过天平哪边向上、向下移动来判断那个假币是轻还是重。
通过仔细选择如何称重,莎莉可以保证,她只需要3次称重就可以找到那枚假币。

输入

第一行输入是一个整数n (n>0) 指明有几组测试数据,每组数据由三行输入组成,一行代表一次称重。莎莉用字母A到L标记了所有硬币。每次称重的信息都包括两个字母字符串,与“up”、“down”、“even”三个单词中的一个词。第一个字母字符串表示天平左盘的硬币,第二个字母字符串则是天平右盘的硬币(莎莉总是在天平的左右两盘分别放入相同数量的银元)。第三个位置的单词是表明天平的右边是会向上移动、向下移动,还是保持平衡。

输出

对于每组数据,输出字母来表明哪一个是假币,并判断它是更重还是更轻。解决方案始终唯一确定。
这句话第一个字母为假币对应的字母,最后一个单词为:light(更轻)或heavy(更重)。

来源

East Central North America 1998

【解题思路】

一共有A–L共十二枚硬币,其中一枚假币,假币可能更轻或更重。
所以可能的情况有:
0更轻,0更重,1更轻,1更重,…,11更轻,11更重。一共24种情况。
枚举这24种情况,看哪种情况下,输入指定的三次天平比较结果与实际的结果相同。

假设输入为:ABCI EFJK up
如果我假设A是更轻的假币,那么右端应该下沉,实际的结果是右端上翘,与实际结果不同。
如果我假设A是更重的假币,那么右端应该上翘,与实际结果相同。

如果在当前假币情况下,输入指定的三次天平比较的结果与实际结果都相同,那么此时假币的情况就是真实的,可行的。否则该假币情况不可行。

【题解代码】

解法1:
  • C风格
#include<bits/stdc++.h>
using namespace std;
#define N 15
bool hasCh(char s[], char c)//字符串s中是否包含字符c 
{
    int len = strlen(s);
    for(int i = 0; i < len; ++i)
        if(s[i] == c)
            return true;
    return false;
}
void check(bool ishev, bool hl, bool hr, char res[])//ishev表示假币是否更重,hl表示左侧是否有假币 ,hr表示右侧是否有假币,res保存结果字符串
{
    if(!hl && !hr)
        strcpy(res, "even");
    else if(!ishev && !hl && hr || ishev && hl && !hr)//更轻的在右边,或更重的在左边 
        strcpy(res, "up");
    else if(!ishev && hl && !hr || ishev && !hl && hr)//更轻的在左边,或更重的在右边 
        strcpy(res, "down");
}
int main()
{
    char s[4][4][N], lh[2][N] = {"light", "heavy"}, res[N];//输入的字符串 
    int n;
    scanf("%d", &n);
    bool isMatch, isHeavy;
    while(n--)
    {
        for(int i = 1; i <= 3; ++i)
            scanf("%s %s %s", s[i][1], s[i][2], s[i][3]);
        for(char c = 'A'; c <= 'L'; ++c)//假设假币为c 
        {
            for(int k = 0; k < 2; ++k)//假设假币为lh[k],可能的值为light更轻,或heavy更重 
            {
                isMatch = true, isHeavy = strcmp(lh[k], "heavy") == 0; 
                for(int j = 1; j <= 3; ++j)//看比较规则j 
                {
                    bool hl = hasCh(s[j][1], c), hr = hasCh(s[j][2], c);
                    check(isHeavy, hl, hr, res);
                    if(strcmp(res, s[j][3]) != 0)//如果当前假币情况得到的结果与预设结果不同 
                    {
                        isMatch = false;
                        break;
                    }
                }
                if(isMatch)
                {
                    printf("%c is the counterfeit coin and it is %s.\n", c, lh[k]);
                    break;
                }
            }
            if(isMatch)
                break;
        }
    }
    return 0;
}
  • C++风格
#include<bits/stdc++.h>
using namespace std;
bool hasCh(string s, char c)//判断s中是否有c 
{
    for(int i = 0; i < s.length(); ++i)
        if(s[i] == c)
            return true;
    return false;
}
string getRes(char f, string lh, string s1, string s2)//f是假币,lh:字符串 表示更重或更轻,天平两边是s1,s2,看能得到什么结果 
{
    bool h1 = hasCh(s1, f), h2 = hasCh(s2, f);//h1:s1中是否有f,h2:s2中是否有f
    if(h1 == false && h2 == false)
        return "even";
    else if(h1 == true && h2 == false)
    {
        if(lh == "heavy")
            return "up";
        else
            return "down";
    }
    else if(h1 == false && h2 == true)
    {
        if(lh == "heavy")
            return "down";
        else
            return "up";
    }
}
int main()
{
    bool isMatch;
    int n;
    cin >> n;
    string s[4][4];
    string lh[2] = {"light", "heavy"};
    while(n--)
    {
        for(int i = 1; i <= 3; ++i)
            for(int j = 1; j <= 3; ++j) 
                cin >> s[i][j];
        for(char c = 'A'; c <= 'L'; ++c)//假设假币为c 
        {
            for(int k = 0; k < 2; ++k)//假设假币为lh[k],可能的值为light更轻,或heavy更重 
            {
                isMatch = true;//当前假币情况是否可以让3次天平的结果都是预设结果。 
                for(int i = 1; i <= 3; ++i)
                {
                    if(getRes(c, lh[k], s[i][1], s[i][2]) != s[i][3])//如果当前假币情况得到的结果与预设结果不同 
                    { 
                        isMatch = false;            
                        break;
                    }
                }
                if(isMatch)
                {
                    cout << c << " is the counterfeit coin and it is " << lh[k] << '.' << endl;
                    break;
                }
            }
            if(isMatch)//如果找到合适的假币,则跳出 
                break;
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值