算法竞赛入门经典 例题3-4

UVa340

Master-Mind Hints

书上对于这道题目的描述太简短了,应该参考一下英文原题,否则很难直接想到书上的思路,这里来捋一下我是如何想到书上的思路的:

  • 如果存在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
*/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值