很坑爹 。。。
-------------------------------------------------------------------------------------------------------
-
Time Limit:
- 1000ms Memory Limit:
- 65536kB
-
Description
- 赛利有12枚银币。其中有11枚真币和1枚假币。假币看起来和真币没有区别,但是重量不同。但赛利不知道假币比真币轻还是重。于是他向朋友借了一架天平。朋友希望赛利称三次就能找出假币并且确定假币是轻是重。例如:如果赛利用天平称两枚硬币,发现天平平衡,说明两枚都是真的。如果赛利用一枚真币与另一枚银币比较,发现它比真币轻或重,说明它是假币。经过精心安排每次的称量,赛利保证在称三次后确定假币。 Input
-
第一行有一个数字n,表示有n组测试用例。
对于每组测试用例:
输入有三行,每行表示一次称量的结果。赛利事先将银币标号为A-L。每次称量的结果用三个以空格隔开的字符串表示:天平左边放置的硬币 天平右边放置的硬币 平衡状态。其中平衡状态用``up'', ``down'', 或 ``even''表示, 分别为右端高、右端低和平衡。天平左右的硬币数总是相等的。
Output - 输出哪一个标号的银币是假币,并说明它比真币轻还是重(heavy or light)。 Sample Input
-
1 ABCD EFGH even ABCI EFJK up ABIJ EFGH even
Sample Output
K is the counterfeit coin and it is light.
---------------------------------------------------------------------
最开始的想法为先将所有正常的硬币找出来(even两端的),然后对于三次称量结果,读每次称量左右的硬币,如果硬币不是正常的,那么根据称量的结果(up或者down)可以判断出硬币的轻重。这种想法对于题目中例子能够判断出正确结果,但是对于测试数据如
ABCD EFGH even
IJ KA up
JK AB up
不能得出正确结果,首先只能判断出正常的八个硬币,其余的四个硬币都出现在了up或者down的语句中,这样的结果是不正确的。
然后考虑将称量的语句分类,将生成up_left,up_right,down_left,down_right字符串,每次读到了相应语句,则将左右的字母分别加到相应的字符串末尾,然后对于12个硬币,依次判断
for(i=0;i<12;i++){
c='A'+i;
if(even.toString().indexOf(c)!=-1)
continue;
if(!up_right.toString().equals("")&&!down_left.toString().equals("")){
if(up_right.toString().indexOf(c)!=-1&&down_left.toString().indexOf(c)!=-1){
sresult=(char)c+" is the counterfeit coin and it is light.";
break;
}
}
else if(up_right.toString().equals("")&&!down_left.toString().equals("")){
if(down_left.toString().indexOf(c)!=-1){
sresult=(char)c+" is the counterfeit coin and it is light.";
break;
}
}
else if(down_left.toString().equals("")&&!up_right.toString().equals("")){
if(up_right.toString().indexOf(c)!=-1){
sresult=(char)c+" is the counterfeit coin and it is light.";
break;
}
}
if(!up_left.toString().equals("")&&!down_right.toString().equals("")){
if(up_left.toString().indexOf(c)!=-1&&down_right.toString().indexOf(c)!=-1){
sresult=(char)c+" is the counterfeit coin and it is heavy.";
break;
}
}
else if(up_left.toString().equals("")&&!down_right.toString().equals("")){
if(down_right.toString().indexOf(c)!=-1){
sresult=(char)c+" is the counterfeit coin and it is heavy.";
break;
}
}
else if(down_right.toString().equals("")&&!up_left.toString().equals("")){
if(up_left.toString().indexOf(c)!=-1){
sresult=(char)c+" is the counterfeit coin and it is heavy.";
break;
}
}
}
结果对于测试数据
ABCD
EFGH even
IJ KA up
JK AB up
还是不能得到正确的结果,因为此数据中只有up,那么一旦一个硬币出现在了up_left中,那么它就会被判断为重。
然后看了书上的思路,发现是对于每一个硬币,放入三条称量语句中判断它是否轻或者重,
int isLight(char c)
{
int j;
for (j=0;j<3;j++)
{
if (s[j][2][0]=='u')
{
//如果该字母出现在up右端(高的那端),那么它就不是轻的
if (strchr(s[j][1],c)!=NULL)
return false;
}
if (s[j][2][0]=='e')
{
//如果该字母出现在平衡称量语句中
if (strchr(s[j][0],c)||strchr(s[j][1],c))
return false;
}
if (s[j][2][0]=='d')
{
//如果该字母出现在down左端(高的那端),那么它就不是轻的
if (strchr(s[j][0],c)!=NULL)
return false;
}
}
return true;
}
但是这种思路其实是错误的,出现在高的那端除了轻的硬币还可能是正常的硬币。
于是改代码如下
int isLight(char c)
{
int j;
for (j=0;j<3;j++)
{
if (s[j][2][0]=='u')
{
//如果该字母没有出现在up右端(高的那端),那么它就一定不是轻的
if (strchr(s[j][1],c)==NULL)
return false;
}
if (s[j][2][0]=='e')
{
if (strchr(s[j][0],c)||strchr(s[j][1],c))
return false;
}
if (s[j][2][0]=='d')
{
//如果该字母没有出现在down左端(高的那端),那么它就一定不是轻的
if (strchr(s[j][0],c)==NULL)
return false;
}
}
return true;
}
另一个函数int isHeavy(char c)同理
#include <iostream>
#include "string.h"
using namespace std;
char s[3][3][13];
int isLight(char c)
{
int j;
for (j=0;j<3;j++)
{
if (s[j][2][0]=='u')
{
//如果该字母没有出现在up右端(高的那端),那么它就一定不是轻的
if (strchr(s[j][1],c)==NULL)
return false;
}
if (s[j][2][0]=='e')
{
if (strchr(s[j][0],c)||strchr(s[j][1],c))
return false;
}
if (s[j][2][0]=='d')
{
//如果该字母没有出现在down左端(高的那端),那么它就一定不是轻的
if (strchr(s[j][0],c)==NULL)
return false;
}
}
return true;
}
int isHeavy(char c)
{
int j;
for (j=0;j<3;j++)
{
if (s[j][2][0]=='u')
{
if (strchr(s[j][0],c)==NULL)
return false;
}
if (s[j][2][0]=='e')
{
if (strchr(s[j][0],c)||strchr(s[j][1],c))
return false;
}
if (s[j][2][0]=='d')
{
if (strchr(s[j][1],c)==NULL)
return false;
}
}
return true;
}
int main()
{
int T,i;
char c;
cin>>T;
while(T--)
{
cin>>s[0][0]>>s[0][1]>>s[0][2]>>s[1][0]>>s[1][1]>>s[1][2]>>s[2][0]>>s[2][1]>>s[2][2];
for (i=0;i<12;i++)
{
c=(char)(i+'A');
if (isLight(c))
{
cout<<c<<" is the counterfeit coin and it is light."<<endl;
break;
}
if (isHeavy(c))
{
cout<<c<<" is the counterfeit coin and it is heavy."<<endl;
break;
}
}
}
}