題目鏈接
給你n個硬幣,硬幣的編號從1到n,n個硬幣中有一個硬幣是假的,他的重量與真硬幣的質量不一樣,或重或輕,真硬幣的重量都相同。給你k組測量結果,判斷是否能找出假硬幣。每組結果分爲2行,第一行第一個數字代表秤盤左右硬幣的個數m,前m個表示左秤盤的硬幣編號,後m個表示右秤盤的硬幣數量,第二行是測量結果(= < >)三者之一。判斷k組結果能否找出假硬幣,能輸出硬幣的編號,否則輸出0。
拿到該題目第一反應不知道如何下手,需要綜合每一組測量的結果才能進行判斷,所以我們需要把每一步的結果進行分析並保持。
- 結果爲等號兩邊的硬幣一定是真硬幣,我們做上true的標記
- 結果爲不等號的硬幣一定含有假硬幣,我們將輕硬幣在left數組標記,將重硬幣在right數組標記
- 因爲只有一個假硬幣,硬幣不會一會兒輕,一會重。由於不等號出現的結果必定是應爲假硬幣的出現,所以硬幣在left/right數組出現的次數與不等號結果的次數相同則爲假硬幣。
- 如果滿足以上的結果只有一組就給予輸出,否則輸出0
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
const int MAXN = 1e3 + 5;
int a[MAXN], b[MAXN], l[MAXN], r[MAXN];
char s[MAXN];
bool T[MAXN];
vector<int> v;
int main()
{
int n, k;
scanf("%d%d", &n, &k);
int cnt = 0;
for (int j = 0; j < k; ++j)
{
int m;
scanf("%d", &m);// 秤盤測量左右硬幣的個數
for (int i = 0; i < m; ++i)
{
scanf("%d", &a[i]);
}
for (int i = 0; i < m; ++i)
{
scanf("%d", &b[i]);
}
getchar();// 吸收緩衝區scanf殘餘的回車字符
gets(s);
if (strcmp(s, "<") == 0)
{
cnt++;// 不等號出現次數加1
// 標記硬幣在l/r出現的次數
for (int i = 0; i < m; ++i)
{
l[a[i]]++;
}
for (int i = 0; i < m; ++i)
{
r[b[i]]++;
}
}
else if (strcmp(s, "=") == 0)
{
for (int i = 0; i < m; ++i)
{
T[a[i]] = true;
}
for (int i = 0; i < m; ++i)
{
T[b[i]] = true;
}
}
else if (strcmp(s, ">") == 0)
{
cnt++;
for (int i = 0; i < m; ++i)
{
r[a[i]]++;
}
for (int i = 0; i < m; ++i)
{
l[b[i]]++;
}
}
}
for (int i = 1; i <= n; ++i)
{
// 非真硬幣,且出現次數與不等號次數一致一定爲假硬幣
if (!T[i] && (l[i] == cnt || r[i] == cnt))
{
v.push_back(i);
}
}
// 判斷假硬幣的可能結果
if (v.size() == 1)
{
printf("%d", v[0]);
}
else
{
printf("0");
}
return 0;
}