PKU ACM 1013 Counterfeit Dollar 假币

本文介绍了一种利用天平称重三次的方法来找出12枚钱币中唯一一枚伪币的策略,该伪币重量不同于真币,但未知是轻还是重。通过逻辑分析和分组称重,实现快速定位伪币。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接伪币 Counterfeit Dollar


问题描述

12枚钱币,其中一枚是假的。假币的重量和真币不同,但是不知道比真币轻还是重。用天平称 3 次,找到那枚假币。


主要思路

1. 如果天平两边重量相同,则说明两边的钱币都是真的;

2. 如果天平两边重量不同,则说明其他的硬币都是真的(因为只有一枚假币);

3. 如果有一枚硬币既出现在轻的一端,也曾出现在重的一端,则说明它是真币;

注意天平两端不一定是 4 枚硬币,几次 WA 都是这个原因。


源代码

#include <iostream>
#include <string>
using namespace std;

int coins[12] = {0};
string scoins = "ABCDEFGHIJKL";

void GetRealCoin(string s)
{
	for(int i = 0; i < s.length(); i++)
		coins[s[i] - 'A'] = 2;
}

bool CharinString(char c, string s)
{
	for(int i = 0; i < s.length(); i++)
	{
		if(c == s[i])
			return true;
	}
	return false;
}

void GetOthers(string s)
{
	for(int i = 0; i < 12; i++)
	{
		if(!CharinString(scoins[i], s))
			coins[i] = 2;
	}
}

void GetRealFromLH(string* lightcoins, string* heavycoins)
{
	bool lightflag, heavyflag;
	for(int i = 0; i < 12; i++)
	{
		lightflag = false;
		heavyflag = false;
		for(int j = 0; j < 3; j++)
		{
			if(CharinString(scoins[i], lightcoins[j]))
				lightflag = true;
			if(CharinString(scoins[i], heavycoins[j]))
				heavyflag = true;
			if(lightflag && heavyflag)
				coins[i] = 2;
		}
	}
}

int main()
{
	int number = 0;
	string left, right, balance;
	string lightcoins[3];
	string heavycoins[3];
	
	cin >> number;
	while(number--)
	{
		memset(coins, 0, sizeof(coins));
		left = right = balance = "";
		for(int n = 0; n < 3; n++)
		{
			lightcoins[n] = "";
			heavycoins[n] = "";
		}
		for(int i = 0; i < 3; i++)
		{
			cin >> left >> right >> balance;

			if(balance == "even")
			{
				GetRealCoin(left + right);
			}
			else if(balance == "up")
			{
				GetOthers(left + right);
				lightcoins[i] = right;
				heavycoins[i] = left;
			}
			else if(balance == "down")
			{
				GetOthers(left + right);
				lightcoins[i] = left;
				heavycoins[i] = right;
			}
		}

		GetRealFromLH(lightcoins, heavycoins);
		
		int j = 0;
		for(int k = 0; k < 12; k++)
		{
			if(coins[k] != 2)
			{
				for(j = 0; j < 3; j++)
				{
					if(CharinString(scoins[k], lightcoins[j]))
					{
						cout << scoins[k] << " is the counterfeit coin and it is light." << endl;
						break;
					}
				}
				if(j == 3)
					cout << scoins[k] << " is the counterfeit coin and it is heavy." << endl;
			}
		}
	}

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值