POJ 1013 Counterfeit Dollar

Counterfeit Dollar
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 32404 Accepted: 10211

Description

Sally Jones has a dozen Voyageur silver dollars. However, only eleven of the coins are true silver dollars; one coin is counterfeit even though its color and size make it indistinguishable from the real silver dollars. The counterfeit coin has a different weight from the other coins but Sally does not know if it is heavier or lighter than the real coins.
Happily, Sally has a friend who loans her a very accurate balance scale. The friend will permit Sally three weighings to find the counterfeit coin. For instance, if Sally weighs two coins against each other and the scales balance then she knows these two coins are true. Now if Sally weighs
one of the true coins against a third coin and the scales do not balance then Sally knows the third coin is counterfeit and she can tell whether it is light or heavy depending on whether the balance on which it is placed goes up or down, respectively.
By choosing her weighings carefully, Sally is able to ensure that she will find the counterfeit coin with exactly three weighings.

Input

The first line of input is an integer n (n > 0) specifying the number of cases to follow. Each case consists of three lines of input, one for each weighing. Sally has identified each of the coins with the letters A--L. Information on a weighing will be given by two strings of letters and then one of the words ``up'', ``down'', or ``even''. The first string of letters will represent the coins on the left balance; the second string, the coins on the right balance. (Sally will always place the same number of coins on the right balance as on the left balance.) The word in the third position will tell whether the right side of the balance goes up, down, or remains even.

Output

For each case, the output will identify the counterfeit coin by its letter and tell whether it is heavy or light. The solution will always be uniquely determined.

Sample Input

1 
ABCD EFGH even 
ABCI EFJK up 
ABIJ EFGH even 

Sample Output

K is the counterfeit coin and it is light. 

Source



题目分析:刚开始还在想,怎么根据这三次实验来推断出哪个是假的,于是就想到,根据每次实验的结果,要进行各种推断,不过这些推断规则很难想全了。然后突然之间想到一个很简单的方法:既然题目保证解的唯一性,而且解空间也不大(12*2=24),因此对于这24种可能性:A是假的,并且是轻的,A是假的,并且是重的,B是假的,并且是轻的,B是假的,并且是重的,...,刚好是24种可能性。肯定是只有一个适合的,而其他的都是跟三次实验中至少一次实验不符合的。因此我们把每一种可能性都代入到三次实验中,看是否符合,如果符合,那么就得到了解。

如何检验一个解与一次实验是否符合呢?很简单:如果这次实验结果是“even”,那么说明假的硬币没有包含在这次实验中;如果结果是"up",而且要验证的解是“假硬币轻”,那么显然此时假硬币应该包含在天平右边,...,通过这些简单的检验,就可以判断一个解是否跟一组实验符合。

采用这种思路编写出代码后,一次就通过了, 代码如下:


package poj1013;

import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner in=new Scanner(System.in);
		int n=in.nextInt();
		for(int i=0;i<n;i++){
			String[][] info=new String[3][3];
			//读取数据
			for(int j=0;j<3;j++){
				for(int k=0;k<3;k++){
					info[j][k]=in.next();
				}
			}
			
			//
			for(char c='A';c<='L';c++){
				if(check(info, c, true)){
					System.out.println(c+" is the counterfeit coin and it is heavy.");
					break;
				}
				if(check(info, c, false)){
					System.out.println(c+" is the counterfeit coin and it is light.");
					break;
				}
			}
			
		}
		
	}
	static boolean check(String[][] info, char c, boolean heavy){
		for(String [] strArray:info){
			if(strArray[2].equals("even")){//then c should not appear
				for(char c1:strArray[0].toCharArray()){
					if(c1==c)return false;
				}
				for(char c1:strArray[1].toCharArray()){
					if(c1==c)return false;
				}
			}else if((strArray[2].equals("up")&&heavy)||(strArray[2].equals("down")&&!heavy)){
				boolean include=false;
				for(char c1:strArray[0].toCharArray()){
					if(c1==c){
						include=true;
						break;
					}
				}
				if(!include)return false;
			}else{
				boolean include=false;
				for(char c1:strArray[1].toCharArray()){
					if(c1==c){
						include=true;
						break;
					}
				}
				if(!include)return false;
			}
		}
		return true;
	}

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值