2692:假币问题

2692:假币问题

#include <bits/stdc++.h>
using namespace std;
char Left[3][7];
char Right[3][7];
char result[3][5]; 
bool  isFake(char c,bool light){//假设c是假币,是否更轻
	for(int i=0;i<3;i++){
		char *fleft;
		char *fright;
		 if(light==true){
		 	fleft=Left[i];
		 	fright=Right[i];
		 }
		 else if(light==false){
		 	fleft=Right[i];//if假币更重,那么验出哪边轻,假币就在另一边,
//	早早调换好顺序,因为fleft就是用来指向假币所在字符串来找假币的 
		 	fright=Left[i];
		 }
		 char res=result[i][0];
		 switch(res){
		 	case 'u'://右边的翘起,说明右边更轻,假币在右边 
		 	if(strchr(fright,c)==NULL){//在右边没有找到更轻的那枚币 
		 		return false;
		 	//	break;一定要break呀,如果找到了说明这次称量证明假设成立 
			 }	
			 break; 
			case 'e'://两侧平衡,说明称的硬币里没有假的 
		 	if(strchr(fright,c)||strchr(fleft,c)){//如果找到了假币 
		 		return false;
			 }
			 	break;
			case 'd'://右边的沉下,说明右边更重,假币在左边 
		 	if(strchr(fleft,c)==NULL){//在左边没有找到更轻的那枚币 
		 		return false;
			 }
			break;
		 } 
	}
	return true;//三次称量结果都与假设结果符合时,才证明假设成立 
}
int main(int argc, char** argv) {

	int t;
	cin>>t;
	while(t--){
		for(int i=0;i<3;i++){
			cin>>Left[i]>>Right[i]>>result[i];
		}
		for(char c='A';c<='L';c++){//假设第i枚硬币是假币
			if(isFake(c,true)){//假设第i枚硬币是假币且轻于真币 
			printf("%c is the counterfeit coin and it is light. \n",c);	
			}
			else if(isFake(c,false)){//假设第i枚硬币是假币且重于真币 
			printf("%c is the counterfeit coin and it is heavy. \n",c);	
			}
		}
	}
 
		return 0;
	}
	//两种思路:
//方法一、对12枚硬币进行枚举,分别假设第i枚硬币是假币且分别为轻、重
//的情况 ,在已知的更轻/重的那一边寻找这枚假币,找到了假币说明成立
//方法二、对硬币编号1~12,设正常重量为0,轻为-1,重为1,依然是 分别假设第i枚硬币
//是假币且分别为轻、重的情况,不是寻找,而是累加重量来比较轻重,如何通过字母
//确定硬币,字母-'A'即可代表硬币编号  

#include <bits/stdc++.h>
using namespace std;
char Left[3][7];
char Right[3][7];
char result[3][5]; 
int w[12];
bool  isBalance(){//
	for(int i=0;i<3;i++){
		int leftw=0;//给出的三次称量中,左边的重量 
		int rightw=0;
		for(int j=0;j<6&&Left[i][j]!='\0';j++){//左右两边硬币数量相等 
			leftw+=w[Left[i][j]-'A'];
			rightw+=w[Right[i][j]-'A'];
		}
		if(result[i][0]=='u'&&leftw>rightw)continue;
		else if(result[i][0]=='d'&&leftw<rightw)continue;
		else if(result[i][0]=='e'&&leftw==rightw)continue;
		else return false;
	}
	return true;
}
int main(int argc, char** argv) {

	int t;
	cin>>t;
	while(t--){
		for(int i=0;i<3;i++){
			cin>>Left[i]>>Right[i]>>result[i];
		}
		memset(w,0,sizeof(w));
		int i=0;
		for( i=0;i<12;i++){
			w[i]=-1;//假设第i枚硬币为假的,且更轻
			if(isBalance()){
				break;
			} 
			w[i]=1;//假设第i枚硬币为假的,且更重 
			if(isBalance()){
				break;
			} 
			w[i]=0;//第i枚是假币不成立,那i枚硬币就是真的 
		}
		printf("%c is the counterfeit coin and it is %s. \n",i+'A',w[i]<0?"light":"heavy"); 
	}
 
		return 0;
	}
	//两种思路:
//方法一、对12枚硬币进行枚举,分别假设第i枚硬币是假币且分别为轻、重
//的情况 ,在已知的更轻/重的那一边寻找这枚假币,找到了假币说明成立
//方法二、对硬币编号1~12,设正常重量为0,轻为-1,重为1,依然是 分别假设第i枚硬币
//是假币且分别为轻、重的情况,不是寻找,而是累加重量来比较轻重,如何通过字母
//确定硬币,字母-'A'即可代表硬币编号  

分治法寻找假币法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值