来,题目奉上
图片说明
题意:就是Peterliang有12枚硬币,标号分别为A-L,然后对它进行三次称量,根据称量结果来判断出那枚是假币,它比正常币重还是轻,然后就是按一定的格式输出即可。(大概意思就是这样)具体还要大家自行去理解。
我看了慕课的北京大学那个老师讲的题解,可能是我太菜了,看不懂,只能自己解决了。
思路:我们可以看出来,它只有12枚硬币,而其中一枚要么是更重,要么是更轻,那么,枚举对他来说就再合适不过了。那么,怎么枚举呢?那肯定是从第一个开始枚举,然后分情况判断是重还是轻,然后分别对某种情况下判断是否满足输入的对应的三种结果即可,如果都满足,则说明该情况符合,直接跳出循环即可。(题目说了一定存在)

string c[3][3];
for(int i=0;i<3;i++){  //输入 
    for(int j=0;j<3;j++){
    cin>>c[i][j];
    }
}

这里,为了考虑代码的长度,我们对于每组数据的输入用一个二维的string数组来表示,就比如这样:
表示好了,怎么办呢?这里我们注意到硬币标号是从A-L的,其实这是可以和数字1-12联系起来的,就只要用该字符减去64就行了。
就是这个a[c[j][0][k]-64];这里的c[j][0][k]就是我们在第几次的情况下的硬币的标号,如A等,然后减去64,就变成了我们的1-12了。
我们用一个整型a数组来表示12枚硬币的轻重,将所有正常的用memset函数初始化为0,如果假币更重就记为1,更轻就记为-1.先看完整的遍历循环吧。

for(int i=1;i<=12;i++){  //枚举每个银币 
            memset(a,0,sizeof(a));  //每次枚举的时候先初始化数组a中的元素为0
            int ans=0;
            a[i]=1;  //假设当前枚举的银币更重 
            for(int j=0;j<3;j++){ 
                int left=0,right=0;
                string temp;
                int len1=c[j][0].length(),len2=c[j][1].length();
                for(int k=0;k<len1;k++){
                    left+=a[c[j][0][k]-64];
                }
                for(int k=0;k<len2;k++){
                    right+=a[c[j][1][k]-64];
                }
                if(right==left)  temp="even";  //将当前假设下的结果先存入temp中等下进行比较
                else if(right<left)   temp="up";
                else  temp="down";
                if(temp!=c[j][2]) break;
                else  ans++;  //满足输入的其中一种情况,ans自增
            }
            if(ans==3){  //三次都满足,则跳出循环
                flag=i;
                temp="heavy";
                break;
            }
           //下面的代码其实就是假设当前的硬币更轻的情况,和上面的思路一样的
            a[i]=-1,ans=0;  //假设更轻 
            for(int j=0;j<3;j++){  
                int left=0,right=0;
                string temp;
                int len1=c[j][0].length(),len2=c[j][1].length();
                for(int k=0;k<len1;k++){
                    left+=a[c[j][0][k]-64];
                }
                for(int k=0;k<len2;k++){
                    right+=a[c[j][1][k]-64];
                }
                if(right==left)  temp="even";
                else if(right<left)   temp="up";
                else  temp="down";
                if(temp!=c[j][2]) break;
                else  ans++;
            }
            if(ans==3){
                flag=i;   //flag用来标记是哪枚假币
                temp="light";  //这个temp是记录改假币的重量情况
                break;
            } 
}

对于每次枚举,先将存放所有硬币的元素重量的数组a初始化为0,因为这是多组测试。这里的ans是用来记录是否三种情况都满足的。大家不要认为这代码很长,其实只要弄懂一半就行了。我们先令当前枚举的条件下的硬币的质量为1(是假币且更重),然后根据输入的数据来看是否满足对应的输入结果(重,或者轻,或者一样)。当前枚举情况下的我们存在字符串temp之中,然后与输入的相应结果比较,如果三次都满足输入对应的条件,那么当前假设成立,跳出循环输出即可。

#include<iostream>
#include<cstring>
using namespace std;
int main(){
    int t;
    cin>>t;
    while(t--){
        string c[3][3];
        for(int i=0;i<3;i++){  //输入三次称量的情况 
            for(int j=0;j<3;j++){
                cin>>c[i][j];
            }
        }
        int a[13];
        string temp;  //用来存储假设的重量情况,方便输出 
        int flag;   //用来标记假设成立的硬币的下标 
        for(int i=1;i<=12;i++){  //枚举每个银币 
            memset(a,0,sizeof(a));
            int ans=0;
            a[i]=1;  //假设当前枚举的银币更重 
            for(int j=0;j<3;j++){    //对三次的称量结果进行分析 
                int left=0,right=0;
                string temp;
                int len1=c[j][0].length(),len2=c[j][1].length();
                for(int k=0;k<len1;k++){
                    left+=a[c[j][0][k]-64];   
                }
                for(int k=0;k<len2;k++){
                    right+=a[c[j][1][k]-64];
                }
                if(right==left)  temp="even";  //记下第一种输入情况下的天平的平衡情况 
                else if(right<left)   temp="up";
                else  temp="down";
                if(temp!=c[j][2]) break;
                else  ans++;   //满足一种对应情况ans自增 
            }
            if(ans==3){  //三次都满足则直接跳出循环,表示找到了该假币和他的情况 
                flag=i;
                temp="heavy";  //并将假设的情况先存在temp之中 
                break;
            }
            //下面这个代码其实本质就是和上面一样 
            a[i]=-1,ans=0;  //假设更轻 
            for(int j=0;j<3;j++){  
                int left=0,right=0;
                string temp;
                int len1=c[j][0].length(),len2=c[j][1].length();
                for(int k=0;k<len1;k++){
                    left+=a[c[j][0][k]-64];
                }
                for(int k=0;k<len2;k++){
                    right+=a[c[j][1][k]-64];
                }
                if(right==left)  temp="even";
                else if(right<left)   temp="up";
                else  temp="down";
                if(temp!=c[j][2]) break;
                else  ans++;
            }
            if(ans==3){
                flag=i;
                temp="light";
                break;
            } 
        }
        char key=flag+64;   //表示A-L中的某一下标 
        cout<<key<<" is the counterfeit coin and it is "<<temp<<"."<<endl;  //输出第几枚硬币是假币和其质量情况 
    }
    return 0;
}

这样就轻松ac了,(好吧,其实一点也不轻松),有问题欢迎下方留言。