来,题目奉上
题意:就是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了,(好吧,其实一点也不轻松),有问题欢迎下方留言。