poj 2692 假幣問題

很坑爹 。。。

-------------------------------------------------------------------------------------------------------

Time Limit: 
1000ms 
Memory Limit: 
65536kB
Description
賽利有12枚銀幣。其中有11枚真幣和1枚假幣。假幣看起來和真幣沒有區別,但是重量不同。但賽利不知道假幣比真幣輕還是重。於是他向朋友借了一架天平。朋友希望賽利稱三次就能找出假幣並且確定假幣是輕是重。例如:如果賽利用天平稱兩枚硬幣,發現天平平衡,說明兩枚都是真的。如果賽利用一枚真幣與另一枚銀幣比較,發現它比真幣輕或重,說明它是假幣。經過精心安排每次的稱量,賽利保證在稱三次後確定假幣。
Input
第一行有一個數字n,表示有n組測試用例。
對於每組測試用例:
輸入有三行,每行表示一次稱量的結果。賽利事先將銀幣標號爲A-L。每次稱量的結果用三個以空格隔開的字符串表示:天平左邊放置的硬幣 天平右邊放置的硬幣 平衡狀態。其中平衡狀態用``up'', ``down'', 或 ``even''表示, 分別爲右端高、右端低和平衡。天平左右的硬幣數總是相等的。
Output
輸出哪一個標號的銀幣是假幣,並說明它比真幣輕還是重(heavy or light)。
Sample Input
1
ABCD EFGH even 
ABCI EFJK up 
ABIJ EFGH even 

Sample Output
K is the counterfeit coin and it is light. 

---------------------------------------------------------------------

      最開始的想法爲先將所有正常的硬幣找出來(even兩端的),然後對於三次稱量結果,讀每次稱量左右的硬幣,如果硬幣不是正常的,那麼根據稱量的結果(up或者down)可以判斷出硬幣的輕重。這種想法對於題目中例子能夠判斷出正確結果,但是對於測試數據如

ABCD EFGH even
IJ KA up
JK AB up

不能得出正確結果,首先只能判斷出正常的八個硬幣,其餘的四個硬幣都出現在了up或者down的語句中,這樣的結果是不正確的。

     然後考慮將稱量的語句分類,將生成up_left,up_right,down_left,down_right字符串,每次讀到了相應語句,則將左右的字母分別加到相應的字符串末尾,然後對於12個硬幣,依次判斷

for(i=0;i<12;i++){
				c='A'+i;
				if(even.toString().indexOf(c)!=-1)
					continue;
				if(!up_right.toString().equals("")&&!down_left.toString().equals("")){
					if(up_right.toString().indexOf(c)!=-1&&down_left.toString().indexOf(c)!=-1){
						sresult=(char)c+" is the counterfeit coin and it is light.";
						break;
					}
				}
				else if(up_right.toString().equals("")&&!down_left.toString().equals("")){
					if(down_left.toString().indexOf(c)!=-1){
						sresult=(char)c+" is the counterfeit coin and it is light.";
						break;
					}
				}
				else if(down_left.toString().equals("")&&!up_right.toString().equals("")){
					if(up_right.toString().indexOf(c)!=-1){
						sresult=(char)c+" is the counterfeit coin and it is light.";
						break;
					}
				}
				
				if(!up_left.toString().equals("")&&!down_right.toString().equals("")){
					if(up_left.toString().indexOf(c)!=-1&&down_right.toString().indexOf(c)!=-1){
						sresult=(char)c+" is the counterfeit coin and it is heavy.";
						break;
					}
				}
				else if(up_left.toString().equals("")&&!down_right.toString().equals("")){
					if(down_right.toString().indexOf(c)!=-1){
						sresult=(char)c+" is the counterfeit coin and it is heavy.";
						break;
					}
				}
				else if(down_right.toString().equals("")&&!up_left.toString().equals("")){
					if(up_left.toString().indexOf(c)!=-1){
						sresult=(char)c+" is the counterfeit coin and it is heavy.";
						break;
					}
				}
			}

結果對於測試數據

ABCD EFGH even
IJ KA up
JK AB up

還是不能得到正確的結果,因爲此數據中只有up,那麼一旦一個硬幣出現在了up_left中,那麼它就會被判斷爲重。


然後看了書上的思路,發現是對於每一個硬幣,放入三條稱量語句中判斷它是否輕或者重,

int isLight(char c)
{
	int j;
	for (j=0;j<3;j++)
	{
		if (s[j][2][0]=='u')
		{
			//如果該字母出現在up右端(高的那端),那麼它就不是輕的
			if (strchr(s[j][1],c)!=NULL)
				return false;
		}
		if (s[j][2][0]=='e')
		{
			//如果該字母出現在平衡稱量語句中
			if (strchr(s[j][0],c)||strchr(s[j][1],c))
				return false;
		}
		if (s[j][2][0]=='d')
		{
			//如果該字母出現在down左端(高的那端),那麼它就不是輕的
			if (strchr(s[j][0],c)!=NULL)
				return false;
		}
	}
	return true;
}

但是這種思路其實是錯誤的,出現在高的那端除了輕的硬幣還可能是正常的硬幣。

於是改代碼如下

int isLight(char c)
{
	int j;
	for (j=0;j<3;j++)
	{
		if (s[j][2][0]=='u')
		{
			//如果該字母沒有出現在up右端(高的那端),那麼它就一定不是輕的
			if (strchr(s[j][1],c)==NULL)
				return false;
		}
		if (s[j][2][0]=='e')
		{
			if (strchr(s[j][0],c)||strchr(s[j][1],c))
				return false;
		}
		if (s[j][2][0]=='d')
		{
			//如果該字母沒有出現在down左端(高的那端),那麼它就一定不是輕的
			if (strchr(s[j][0],c)==NULL)
				return false;
		}
	}
	return true;
}

另一個函數int isHeavy(char c)同理

#include <iostream>
#include "string.h"
using namespace std;
char s[3][3][13];
int isLight(char c)
{
	int j;
	for (j=0;j<3;j++)
	{
		if (s[j][2][0]=='u')
		{
			//如果該字母沒有出現在up右端(高的那端),那麼它就一定不是輕的
			if (strchr(s[j][1],c)==NULL)
				return false;
		}
		if (s[j][2][0]=='e')
		{
			if (strchr(s[j][0],c)||strchr(s[j][1],c))
				return false;
		}
		if (s[j][2][0]=='d')
		{
			//如果該字母沒有出現在down左端(高的那端),那麼它就一定不是輕的
			if (strchr(s[j][0],c)==NULL)
				return false;
		}
	}
	return true;
}
int isHeavy(char c)
{
	int j;
	for (j=0;j<3;j++)
	{
		if (s[j][2][0]=='u')
		{
			if (strchr(s[j][0],c)==NULL)
				return false;
		}
		if (s[j][2][0]=='e')
		{
			if (strchr(s[j][0],c)||strchr(s[j][1],c))
				return false;
		}
		if (s[j][2][0]=='d')
		{
			if (strchr(s[j][1],c)==NULL)
				return false;
		}
	}
	return true;
}
int main()
{
	int T,i;
	char c;
	cin>>T;
	while(T--)
	{
		cin>>s[0][0]>>s[0][1]>>s[0][2]>>s[1][0]>>s[1][1]>>s[1][2]>>s[2][0]>>s[2][1]>>s[2][2];
		for (i=0;i<12;i++)
		{
			c=(char)(i+'A');
			if (isLight(c))
			{
				cout<<c<<" is the counterfeit coin and it is light."<<endl;
				break;
			}
			if (isHeavy(c))
			{
				cout<<c<<" is the counterfeit coin and it is heavy."<<endl;
				break;
			}
		}
	}
}



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