| 2068160 | 2006-09-15 17:18:10 | Accepted | 1184 | C++ | 00:00.00 | 844K | St.Crux | 
这是一个古老的题目,12枚硬币称3次,求出其中那枚轻或重的硬币。
当然,这道题比求解法简单多了,只需求证明。而我们知道,证明一样物体的存在,只需要把与其对立面的物体从物理层面乃至精神层面完全地、不留遗迹地消灭,这点在人类文明史中得到了最有力的支持......因此,最简单的办法是枚举24种情况,然后一一搜索,不满足者剔除即可。但显然这比较笨拙。
有没有简单一点的办法——假如不是12枚,而是12亿枚?好吧,同样是剔除,我们可以从判断语句入手。
比如 ABCD EFGH even 我们知道了这八枚都是even的。
又比如 ABCI EFJK up 我们知道了ABCI里必然有一枚是heavy的,而EFJK必然有一枚light。因此ABCI就是heavy的嫌疑对象,反之亦然。这是可能性。
从上面的语句中,我们还能得到隐含的条件:DGHL必然是even的。这是必然性。
所以,只要把不满足必然性的可能性剔除就OK了。
至于这个问题的解法,大致是用到二分,具体怎么写还有待研究。
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
using namespace std;
int n, b[12], l0, l1, c[12];
string s0, s1, s2;
void proc();
void print();
int main()
{
 //freopen("in.txt", "r", stdin);
 cin >> n;
 int i, k;
 for(i = 0; i < n; i ++)
 {
  memset(b, 0, sizeof(b));
  for(k = 0; k < 3; k ++)
  {
   cin >> s0 >> s1 >> s2;
   l0 = s0.size(), l1 = s1.size();
   proc();
  }
  print();
 }
 return 0;
}
void proc()
{
 int j, t;
 //cout << s0 << " " <<  s1 << " " <<  s2 << endl;
 memset(c, 0, sizeof(c));
 if(s2 == "even") //两边相等
 {
  for(j = 0; j < l0; j ++)
  {
   t = s0[j] - 'A'; 
   if(b[t] == 2) continue;
   b[t] = 2;  //2代表相等
  }
  for(j = 0; j < l1; j ++)
  {
   t = s1[j] - 'A';
   if(b[t] == 2) continue;
   b[t] = 2; 
  } 
 }
 else if(s2 == "up")  //左边重
 {
  for(j = 0; j < l0; j ++)
  {
   t = s0[j] - 'A';
   c[t] = 1;
   if(b[t] == 2) continue;
   if(b[t] == 1) b[t] = 2;  //有1存在说明这是标准重量
   if(!b[t]) b[t] = 3; //3代表重的可能性   
  }  
  for(j = 0; j < l1; j ++)
  {
   t = s1[j] - 'A';
   c[t] = 1;
   if(b[t] == 2) continue;
   if(b[t] == 3) b[t] = 2;  //有3存在说明这是标准重量
   if(!b[t]) b[t] = 1; //1代表轻的可能性   
  } 
  for(j = 0; j < 12; j ++)
  {
   if(!c[j])
   {
    t = j;
    if(b[t] == 2) continue;
    b[t] = 2;
   }
  }
 }
 else if(s2 == "down")  //右边重
 {
  for(j = 0; j < l0; j ++)
  {
   t = s0[j] - 'A';
   c[t] = 1;
   if(b[t] == 2) continue;
   if(b[t] == 3) b[t] = 2;  
   if(!b[t]) b[t] = 1;    
  }  
  for(j = 0; j < l1; j ++)
  {
   t = s1[j] - 'A';
   c[t] = 1;
   if(b[t] == 2) continue;
   if(b[t] == 1) b[t] = 2;  
   if(!b[t]) b[t] = 3;    
  } 
  for(j = 0; j < 12; j ++)
  {
   if(!c[j])
   {
    t = j;
    if(b[t] == 2) continue;
    b[t] = 2;
   }
  }
 }
 //print();
}
void print()
{
 int i;
 for(i = 0; i < 12; i ++)
 {
  if(b[i] == 2) continue;
  if(b[i] == 1)
  {
   printf("%c is the counterfeit coin and it is light.\n", i + 'A');
  }
  if(b[i] == 3)
  {
   printf("%c is the counterfeit coin and it is heavy.\n", i + 'A');
  }
 }
}
 

评论