我是侦探,找假币

题目:

该题类似题

——The “Gold Bar” bank received information from reliable sources that in their last group of N coins exactly one coin is false and differs in weight from other coins (while all other coins are equal in weight). After the economic crisis they have only a simple balance available (like one in the picture). Using this balance, one is able to determine if the weight of objects in the left pan is less than, greater than, or equal to the weight of objects in the right pan.

In order to detect the false coin the bank employees numbered all coins by the integers from 1 to N, thus assigning each coin a unique integer identifier. After that they began to weight various groups of coins by placing equal numbers of coins in the left pan and in the right pan. The identifiers of coins and the results of the weightings were carefully recorded.

You are to write a program that will help the bank employees to determine the identifier of the false coin using the results of these weightings.

Input
The first line of the input file contains two integers N and K, separated by spaces, where N is the number of coins (2<=N<=1000 ) and K is the number of weightings fulfilled (1<=K<=100). The following 2K lines describe all weightings. Two consecutive lines describe each weighting. The first of them starts with a number Pi (1<=Pi<=N/2), representing the number of coins placed in the left and in the right pans, followed by Pi identifiers of coins placed in the left pan and Pi identifiers of coins placed in the right pan. All numbers are separated by spaces. The second line contains one of the following characters: ‘<’, ‘>’, or ‘=’. It represents the result of the weighting:
‘<’ means that the weight of coins in the left pan is less than the weight of coins in the right pan,
‘>’ means that the weight of coins in the left pan is greater than the weight of coins in the right pan,
‘=’ means that the weight of coins in the left pan is equal to the weight of coins in the right pan.

Output
Write to the output file the identifier of the false coin or 0, if it cannot be found by the results of the given weightings.

Sample Input

5 3
2 1 2 3 4

<
1 1 4
=

1 2 5
=

Sample Output
3

题意:

n枚硬币中只有一枚是假币,假币与真币的区别就是重量不等,先对n枚硬币进行1-n编号,之后通过天平进行多次测量,注意左盘与右盘中放的数量永远是一样的,然后利用多次测量的结果找出假币
如果可以找到,输出假币的编号,否则输出-1

输入解析:

5 3 (5代表5枚硬币,3代表称量3ci)

2 1 2 3 4 (2代表称的两边各放2枚硬币,分别是1,2和2,4)
< (1+2<3+4)

1 1 4 (1代表称的两边各放1枚硬币,分别是1和4)
= (1=4)

1 2 5 (1代表称的两边各放1枚硬币,分别是2和5)
= (2=5)

解题思路:

——假币只有1个,在每一个不等式中假币都会存在,因此只需判断哪个硬币出现的次数和不等式的次数相同,并且该硬币唯一,那它一定是假币。
——反之,如果一枚硬币始终和假币捆绑在一起测量,那我们变无没有办法判断出这两枚中那一枚是真哪一枚是假,此时输出0。

具体操作:
——需要用到两个数组进行标记。

  1. real_date[i]==1表示硬币i是真币。
  2. real_date[i]==0表示硬币i可能是假币,是嫌疑币。
    当判断出是嫌疑币后,轻的一方都suspect_date[i]–,重的一方都suspect_date[i]++。只要该嫌疑币不是假币,那么它一定不会一直只出现在轻的一方或者重的一方,只要进行++和–,那它一定不会和不等式的数量相同。反之,只有假币会一直只出现在轻的一方或者重的一方。

代码:

#include<stdio.h>
#include<string.h>
int raw_data[1010];//原始数据 
int real_data[1010];//真数据 
int suspect_data[1010];//嫌疑数据 
int main()
{
	int n,m;
	while(~scanf("%d %d",&n,&m))
	{
		memset(real_data,0,sizeof(real_data));
		memset(suspect_data,0,sizeof(suspect_data));
		int i;
		int count=0;//记录不等式的个数
		while(m--)
		{
			int p;	
			char str[2];
			scanf("%d",&p);
			for(i=1;i<=2*p;i++)
				scanf("%d",&raw_data[i]);
			scanf("%s",str);
			if(str[0]=='=')
			{
				for(i=1;i<=2*p;i++)
					real_data[raw_data[i]]=1;
			}
			else if(str[0]=='<')//这些硬币中的每一枚硬币都有嫌疑 
			{
				count++;
				for(i=1;i<=p;i++)
					suspect_data[raw_data[i]]--; 
				for(i=p+1;i<=2*p;i++)
					suspect_data[raw_data[i]]++;
				//之所以轻的--与重的++,
				//比如:一枚硬币在不等式1的轻的一边,下次该硬币在不等式2重的的一边
				//那么该硬币必定是真币 
			}
			else if(str[0]=='>')//这些硬币中的每一枚硬币都有嫌疑 
			{
				count++;
				for(i=1;i<=p;i++)
					suspect_data[raw_data[i]]++;
				for(i=p+1;i<=2*p;i++)
					suspect_data[raw_data[i]]--;
			}
		}
		int num=0;//最终确定有嫌疑硬币的个数
		int idx=0;//记录假币编号 
		for(i=1;i<=n;i++)
		{
			if(real_data[i])
				continue;
			if(suspect_data[i]==count||suspect_data[i]==-count)
			{
				num++;
				idx=i; 
			}
		}
		if(num==1)
			printf("%d\n",idx);
		else
			printf("0\n");
	}	
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值