POJ 1013: Counterfeit Dollar

来源:互联网 发布:淘宝联盟什么意思 编辑:程序博客网 时间:2024/04/28 07:34

解题要点 1: 把能够从称重过程中获得的信息弄清楚.
对于所有银币, 单次称重可以提供下列信息:

  • even: 上秤的都是 “good”, 没上秤的都是 “unknown”.
  • up : 没上秤的都是 “good”, 左侧的都可能是 “heavy”, 右侧的都可能是 “light”.
  • down: 没上秤的都是 “good”, 左侧的都可能是 “light”, 右侧的都可能是 “heavy”.

对于每一个位置上的银币, 多次称重可以提供下列信息:

  • 有 1 次是 “good” 的, 就一定是 “good”.
  • 3 次称重结果中既有 “heavy” 又有 “light” 的, 就一定是 “good”.

解题要点 2: 记录称重结果.
三次称重并无次序上的依赖关系, 因此可以用三个独立的阵列分别记录三次称重结果, 最后再合并. 对于每一次称重, 先用没上秤的银币的称重结果旗标初始化阵列, 再为上称的银币逐个写入称重结果旗标. 具体如下:

  • even: 用 “unknown” 旗标初始化阵列, 然后左右两侧银币的对应位置均写入 “good” 旗标.
  • up : 用 “good” 旗标初始化阵列, 然后左侧 / 右侧银币的对应位置写入 “heavy” / “light” 旗标.
  • down: 用 “good” 旗标初始化阵列, 然后左侧 / 右侧银币的对应位置写入 “light” / “heavy” 旗标.

与上述方式相比, 只用一个阵列, 叠加写入每一次的称重结果的方法, 实现起来要麻烦得多.

解题要点 3: 定义旗标.
定义一组恰当的旗标, 会使对称重结果的汇总工作事半功倍. 上文中一共出现了 4 种旗标, 分别为 “good”, “light”, “heavy”, “unknown”. 根据解题要点 1 对多次称重所提供的信息的分析, 可以得出下列规则:

  • good & * & * = good
  • heavy & light & * = good

除此之外还应该有:

  • * & unknown = *

为使上述几条规则能够同时成立, 旗标可按照如下方式定义:

  • unknown: 3 (0011)
  • heavy : 2 (0010)
  • light : 1 (0001)
  • good : 0 (0000)

代码如下:

#include <iostream>#include <vector>using namespace std;int main() {    vector<string> weigh( 3, "ABCDEFGHIJKL" );    string west, east, result;    int n;    cin >> n;    while( n-- != 0 ) {        for( int i = 0; i < 3; ++i ) {            cin >> west >> east >> result;  // west = left, east = right. 为了整齐一点...            int len = west.size();            fill( weigh[i].begin(), weigh[i].end(), result == "even" ? '\3' : '\0' );            for( int j = 0; j < len; ++j ) {                if( result == "even" ) {                    weigh[i][west[j] - 'A'] = '\0';                    weigh[i][east[j] - 'A'] = '\0';                } else if( result == "up" ) {                    weigh[i][west[j] - 'A'] = '\2';                    weigh[i][east[j] - 'A'] = '\1';                } else {                    weigh[i][west[j] - 'A'] = '\1';                    weigh[i][east[j] - 'A'] = '\2';                }            }        }        for( int i = 0; i < 12; ++i ) {            char tmp = weigh[0][i] & weigh[1][i] & weigh[2][i];            if( tmp != '\0' ) {                cout << char( 'A' + i ) << " is the counterfeit coin and it is "                    << ( tmp == '\1' ? "light." : "heavy." ) << endl;                break;            }        }    }}
0 0
原创粉丝点击