False coin

题目链接:http://poj.org/problem?id=1029
False coin
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 19239 Accepted: 5426

Description

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

Source


基本信息:只有且必有一枚金币为假。
推断:
1.若为等式,则等式两边所有金币必为真。
2.若为不等式,则不等式两边必有一枚金币为假,未参加此次称重的所有其它金币均为真。

一开始的思路是使用数组设置金币的unknown,true,doubt三种状态。在所有称重情况输入分析完成之后,
1.若仅有一个为doubt,则可判定假金币所在,
2.若有多个doubt,则为证据不足。
3.若没有doubt但仅有一个unknown,则其为假金币。

但是实际测试时发现这种思路无法解决以下用例:

4 3
2 3 1 2 4
<
2 3 2 1 4
<
1 2 4
=

答案是 3


原因是没法判断出里面的1是真金币。

重新分析之后,对不等式信息做更多的记录。使用flag数组记录金币真假,ture则为真,false则未知但不一定为假。同时使用score数组记录金币在不等式左右的表现:
当<时,若不等式左边的元素flag为false则score--,若不等式右边的元素flag为false则score++
当> 时,若不等式左边的元素flag为false则score++,若不等式右边的元素flag为false则score--
当=时,等式两边元素flag置为true,score置0

统计完成之后找出score绝对值最大的唯一元素即为假金币。

附代码:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;

void initialize(int n, int k)
{
	
}

int main ()
{
	int n, k;
	cin >> n >> k;

	bool flag[n+1];
	int score[n+1];
	memset(flag,false,sizeof(flag));
	
	memset(score,0,sizeof(score));

	int p; 
	for (int i = 0; i < k; i ++)
	{
		cin >> p;
		int left[p],right[p];
		memset(left,0,sizeof(left));
		memset(right,0,sizeof(right));
		for (int j = 0; j < p; j ++) cin >>left[j];
		for (int j = 0; j < p; j ++) cin >> right[j];
		char sym;
		cin >> sym;
		switch(sym){
			case '<':
				for (int j = 0; j < p; j ++)
				{
					int index = left[j];
					if(flag[index] == false) score[index] --; 
				 } 
				for (int j = 0; j < p; j ++)
				{
					int index = right[j];
					if(flag[index] == false) score[index] ++; 
				 } 				 
				break;
			case '>':
				for (int j = 0; j < p; j ++)
				{
					int index = left[j];
					if(flag[index] == false) score[index] ++; 
				 } 
				for (int j = 0; j < p; j ++)
				{
					int index = right[j];
					if(flag[index] == false) score[index] --; 
				 } 					
				break;
			case '=':	
				for (int j = 0; j < p; j ++)
				{
					int index = left[j];
					flag[index] = true;
					score[index] = 0; 
				 } 
				for (int j = 0; j < p; j ++)
				{
					int index = right[j];
					flag[index] = true;
					score[index] = 0; 
				 } 				
				break;
			default: break;
		}
	}


	int max_count = 0;
	int max_index = 0;
	int max_value = -1;
//	cout << "doubt_count: " << doubt_count<<endl;
//	cout << "unknown_count: " << unknown_count<<endl;
	for (int i = 1; i <= n; i ++)
	{
		if (abs(score[i]) > max_value && flag[i] == false)
		{
			max_value = abs(score[i]);
			max_index = i;
			max_count = 1;
		}
		else if (abs(score[i]) == max_value && flag[i] == false)
		{
			max_count ++;
		}
	}
//	cout << "result:" << endl;
//	cout << "doubt_count: " << doubt_count<<endl;
//	cout << "unknown_count: " << unknown_count<<endl;
	if (max_count == 1) cout<< max_index << endl;
	else cout << 0 << endl;
 } 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值