poj1013 Counterfeit Dollar

还以为是dp。。。果然模拟题才是王道

设 f(i, 0)表示命题“金币i是一个较轻的假币”,f(i, 1)表示命题“金币i是一个较重的假币”
由于只有一个假币,所以最后结果的全集A为 { f(1,0), f(1,1),f(2,0),f(2.1) ...... f(12,0), f(12,1) }
每次称量,根据结果,都会排除掉全集里的某些元素。

(1)当称量结果为 s1 == s2的时候
对于任意 j 属于 s1 或者 s2,删除f(j, 0), f(j, 1)
(2)当称量结果为 s1 > s2的时候
对于任意j属于s1,删除f(j, 0)
对于任意k属于s2,删除f(k, 1)
对于任意m不属于s1和s2,删除f(m,0),f(m,1)
(3)当称量结果为 s1 < s2时,交换s1和s2,转化为情况(2)

最后,看看全集A里面还剩下哪一个元素,就知道哪个是金币了

 

#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <algorithm>
using namespace std;


bool f[12][2];
char temp[12];
char str1[20], str2[20], str3[10];


void even(char s1[], char s2[]) {
	int i;
	for (i = 0; s1[i]; ++i) {
		f[s1[i] - 'A'][0] = f[s1[i] - 'A'][1] = false;
	}
	for (i = 0; s2[i]; ++i) {
		f[s2[i] - 'A'][0] = f[s2[i] - 'A'][1] = false;
	}
}

void up(char s1[], char s2[]) {
	int i;
	for (i = 0; i < 12; ++i)
		temp[i] = 'N';
	for (i = 0; s1[i]; ++i) {
		temp[s1[i] - 'A'] = 'L';
	}
	for (i = 0; s2[i]; ++i) {
		temp[s2[i] - 'A'] = 'R';
	}

	for (i = 0; i < 12; ++i) {
		if (temp[i] == 'N') {
			f[i][0] = f[i][1] = false;
		} else if (temp[i] == 'L') {
			f[i][0] = false;
		} else if (temp[i] == 'R') {
			f[i][1] = false;
		}
	}
}


void run() {
	int i;
	for (i = 0; i < 12; ++i)
		f[i][0] = f[i][1] = true;

	for (i = 1; i <= 3; ++i) {
		scanf("%s %s %s", str1, str2, str3);
		if (str3[0] == 'e') even(str1, str2);
		else if (str3[0] == 'u') up(str1, str2);
		else up(str2, str1);
	}

	char letter, lorh;
	for (i = 0; i < 12; ++i) {
		if (f[i][0]) { letter = i + 'A'; lorh = 'L'; break; }
		if (f[i][1]) { letter = i + 'A'; lorh = 'H'; break; }
	}

	printf("%c is the counterfeit coin and it is ", letter);
	if (lorh == 'L') printf("light.\n");
	else printf("heavy.\n");
}


int main() {
	int N;
	scanf("%d", &N);
	while(N--) {
		run();
	}
	return 0;
}


你可能感兴趣的:(poj1013 Counterfeit Dollar)