POJ1013Counterfeit Dollar

Counterfeit Dollar
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 43484   Accepted: 13785

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. 

借鑑一下別人寫的很詳細的講解

大致題意:

有一打(12枚)硬幣,其中有且僅有1枚假幣,11枚真幣

用A~L作爲各個硬幣的代號

假幣可能比真幣略輕,也可能略重

現在利用天枰,根據Input輸入的3次稱量,找出假幣,並輸出假幣是輕還是重。

 

解題思路:

模擬法要考慮的情況較繁瑣,可利用簡單的邏輯推理進行解題。

 

 

注意Input一行代表一次稱量,每行有三個字符串,分別爲

Left   right     status

代表該次稱量時,天枰左盤放的硬幣、天枰右盤放的硬幣、天枰右盤的狀態

 

共三種狀態:

Up:右盤上升,說明右盤可能有輕假幣,也可能左盤有重假幣。

Down:右盤下降,說明右盤可能有重假幣,也可能左盤有輕假幣。

Even:右盤與左盤平衡,由於假幣有且僅有1枚,則說明此時天枰兩邊的硬幣全爲真幣。

 

注意題目的字眼:

1、  有且僅有1枚假幣

2、  假幣相對於真幣的重量,可能輕可能重

3、  只稱量3次,且稱量3次恰好且必能找到假幣

4、  每次稱量時天枰兩邊的硬幣數目一樣

5、  選取哪些硬幣稱量由input決定

 

從3、4、5可知,由於無法知道每次選取稱量的硬幣,那麼3次稱量可能只選用了幾個硬幣,也可能僅有一兩個硬幣沒有選上,那麼用模擬法去記錄每次用於稱量的硬幣的狀態(真假,其中假幣又有輕重之分)並推導沒有被稱量的硬幣狀態(或狀態變化)是很困難的,雖然人很容易做到這點,但計算機卻很難去“推導”,因爲稱量硬幣的方法是無規律的且非常多。

 

那麼只能通過適當轉化問題後用另一種有效的方法去解決。

 

雖然稱量硬幣的方法是無規律且未知的,但是稱量硬幣後的結果卻只有3個,up、down和 even。且當出現even時,天枰兩邊的硬幣必然都爲真幣,假幣必定在餘下的硬幣之間(這是因爲假幣有且只有一枚),那麼我們就可以定義一個標記數組 zero[]去標記even時的真幣,在以後的處理把他們排除在外。

而唯一難以處理的是up和down的狀態,因爲假幣可能輕可能重,則這兩種狀態都無法得知究竟假幣出現在天枰的哪邊。

 

處理up和down狀態方法:

當出現up或down狀態時,天枰兩邊的所有硬幣都應該被懷疑爲假幣(已標記必定爲真幣的硬幣不必被懷疑)。

首先time[]記錄每個硬幣的被懷疑程度,time[i]=0表示該硬幣i不被懷疑(即其可能爲真幣)。定義在up狀態盤的硬幣爲“輕懷疑假幣”,通過“--”操作加深其被懷疑爲輕假幣的程度,“負號”爲輕假幣的懷疑方向;在down狀態盤的硬幣爲“重懷疑假幣”,通過“++”操作加深其被懷疑爲重假幣的程度,“正號”爲重假幣的懷疑方向。

那麼若一枚真幣被懷疑爲“輕假幣”時,它就可能通過下次稱量通過“++”操作取消嫌疑了。初始化所有硬幣的懷疑程度均爲0。

稱量完畢後,找出被懷疑程度最大(注意取絕對值)的硬幣,它就是假幣。而當其懷疑方向爲正時,則其爲重假幣。爲負時,爲輕假幣。


#include <iostream>
#include <stdio.h>
#include <string>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;

char s1[20],s2[20],s[10];
int check['L'+1],time['L'+1];

int main()
{
    int T;
    scanf("%d",&T);

    while(T--)
    {
       // getchar();
        memset(check,0,sizeof check);
        memset(time,0,sizeof time);
        for(int j=0;j<3;j++)
        {
            scanf("%s%s%s",s1,s2,s);
            //cout<<s1<<"     "<<s2<<"    "<<s<<"     "<<endl<<"********"<<endl;

            int len1=strlen(s1);
            if(s[0]=='e')
            {
                for(int i=0;i<len1;i++)
                {
                    check[s1[i]]=1;
                    check[s2[i]]=1;
                }
            }
            else if(s[0]=='u')
            {
                for(int i=0;i<len1;i++)
                {
                    time[s1[i]]++;
                    time[s2[i]]--;
                }
            }
            else if(s[0]=='d')
            {
                for(int i=0;i<len1;i++)
                {
                    time[s1[i]]--;
                    time[s2[i]]++;
                }
            }
        }

        char ans;
        int mmax=-1;
        for(char i='A';i<='L';i++)
        {
            if(check[i]) continue;
            if(mmax<=abs(time[i]))
            {
                mmax=abs(time[i]);
                ans=i;
            }
        }
        cout<<ans;
        printf(" is the counterfeit coin and it is ");
        if(time[ans]>0)
            cout<<"heavy.";
        else
            cout<<"light.";
        puts("");

    }
    return 0;
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章