UVa340
书上对于这道题目的描述太简短了,应该参考一下英文原题,否则很难直接想到书上的思路,这里来捋一下我是如何想到书上的思路的:
- 如果存在
s[i] == g[j]
,那么就是一个匹配项;当i == j
时,就是强(strong)匹配,其余都是弱(weak)匹配 - 原题目中提到了independent集合。independent的意思是说,如果选定了匹配关系(i, j),那么
s[i]
就不能再和除g[j]
外的字符匹配了 - 强匹配的数目(也就是书中说的
A
)是很好计算的,但是弱匹配不好直接计算,可以使用总匹配数目减去强匹配数目的方法 - 在遍历guess的过程中,如果当前数字在sercet中出现过,那么是不能直接当做一个匹配项的,需要进一步的判断。因为根据independent的规则,如果选定了匹配项,sercet中对应的字符就不能再使用了,这可能会影响强匹配的计算。因此为了得到所有的匹配项的具体下标,应该是先把强匹配计算出来,然后从sercet和guess中去掉强匹配的字符,接下来就可以用上一条中的方法直接计算弱匹配了
- 不过这道题并没有说计算匹配项的下标,只要进行计数就可以了。强匹配的计数还是之前的方法。按照上一步的思路,在去掉了所有强匹配的情况下,弱匹配的计数应该取sercet和guess中计数值较小的那个,但是因为强匹配在sercet中guess都出现过,所以总匹配的数目也可以去sercet和guess中计数值较小的那个。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n = 0, cnt = 1;
while (cin >> n){
if (n == 0) break;
cout << "Game " << cnt++ << ':' << endl;
vector<int> viSecret(n, 0);
vector<int> viSecretCnt(10, 0);
vector<int> viGuess(n, 0);
for (int i = 0; i < n; i++)
{
cin >> viSecret[i];
viSecretCnt[viSecret[i]]++;
}
while (1){
vector<int> viGuessCnt(10, 0);
int strong = 0, match = 0;
for (int i = 0; i < n; i++)
{
cin >> viGuess[i];
viGuessCnt[viGuess[i]]++;
}
if (viGuess[0] == 0) break;
for (int i = 0; i < n; i++)
{
if (viGuess[i] == viSecret[i]){
strong++;
}
}
for (int i = 1; i < 10; i++)
{
match += viGuessCnt[i] < viSecretCnt[i] ? viGuessCnt[i] : viSecretCnt[i];
}
cout << " (" << strong << ',' << match - strong << ')' << endl;
}
}
return 0;
}
/*
4
1 3 5 5
1 1 2 3
4 3 3 5
6 5 5 1
6 1 3 5
1 3 5 5
0 0 0 0
10
1 2 2 2 4 5 6 6 6 9
1 2 3 4 5 6 7 8 9 1
1 1 2 2 3 3 4 4 5 5
1 2 1 3 1 5 1 6 1 9
1 2 2 5 5 5 6 6 6 7
0 0 0 0 0 0 0 0 0 0
0
*/