算法题:矩阵修改为黑白矩阵

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014573686/article/details/89483333

题目

修改矩阵中的数字,使其成为黑白矩阵。即: (i,j)位置元素的上下左右都两两相同,但是与其不同。不在矩阵范围内的上下左右不考虑。

输入:n,m n行元素,每行m个
输出:修改次数,是一个值

输入示例:
3 3
1 1 1
1 5 1
1 1 1

输出:
4

思路

变成黑白矩阵,矩阵中最后只有两种数字,即一种黑,一种白

矩阵示意图
结果就是圆圈的位置是一种,可以叫做黑,三角的位置是一种,可以叫做白。

根据图可以得到规律,当 行号 % 2 == 列号 % 2 时是一种,否则是另一种,这样就可以得到黑数组和白数组。
要使黑数组中的数全部变成相同的,那么保留重复次数最多的数,修改其他的数,白数组同理。
矩阵的总数 减去 两个重复最多次数的和就是需要修改的次数。
比如 3 * 3的矩阵,黑数组 5 个元素,有3个相同的,那么需要修改的次数就是 2
白数组 4 个元素,有 3 个相同的,那么需要修改的次数就是 1
当这两个数组重复的数不是相同的,比如 黑数组中 3 重复次数最多,白数组 1 重复次数最多,那么直接用矩阵总数 9 减去
黑数组重复元素次数 3 再减去 白数组重复次数 3 结果就是 3

另一种情况,如果黑白数组重复次数最多的元素相同,比如都是 1 重复次数最多, 那么就需要求出黑白数组的第二重复最多的次数a2, b2
然后 a1 + b2 和 a2 + b1哪个大,最终就减去哪个(a1 是黑数组重复次数第一多的,b1是白数组重复次数第一多的)

具体见代码:

#include<iostream>
#include<vector>
#include<unordered_map>
using namespace std;

// 修改矩阵中的数字,使其变为黑白矩阵,即某元素的上下左右元素都相同,且与此元素不同。求最小的修改次数


// 存储最大重复次数的值和次数
typedef struct MaxPair
{
	int time;
	int val;
};

// 找到最大重复次数和值
MaxPair findMaxPair(unordered_map<int, int> mp)
{
	unordered_map<int, int>::iterator iter = mp.begin();
	MaxPair maxP;
	maxP.time = 0;
	
	//int max = 0;
	for (; iter != mp.end(); iter++)
	{
		if (iter->second >= maxP.time)
		{
			maxP.time = iter->second;
			maxP.val = iter->first;
		}
	}
	return maxP;
}

// 找到除某个数外,其余数中重复次数最大的数
MaxPair findMaxPairEK(unordered_map<int, int> mp, int k)
{
	unordered_map<int, int>::iterator iter = mp.begin();
	MaxPair maxP;
	maxP.time = 0;

	//int max = 0;
	for (; iter != mp.end(); iter++)
	{
		if (iter->second >= maxP.time && iter->first != k)
		{
			maxP.time = iter->second;
			maxP.val = iter->first;
		}
	}
	return maxP;
}
int main()
{
	int m, n;
	int val;
	cin >> m >> n;
	vector<vector<int>> arr;
	for (int i = 0; i < n; i++)
	{
		vector<int> sArr;
		for (int j = 0; j < m; j++)
		{
			cin >> val;
			sArr.push_back(val);
		}
		arr.push_back(sArr);
	}
	vector<int> black;
	vector<int> white;
	// 黑白数组初始化
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			if (i % 2 == j % 2)
			{
				black.push_back(arr[i][j]);
			}
			else
			{
				white.push_back(arr[i][j]);
			}
		}
	}
	// 计算重复数的最大值
	unordered_map<int, int> aMap;
	unordered_map<int, int> wMap;

	// 键值对存储重复次数
	unordered_map<int, int>::iterator iter;
	for (int i = 0; i < black.size(); i++)
	{
		// 有了
		if ((iter = aMap.find(black[i])) != aMap.end())
		{
			(iter->second)++;
		}
		else
		{
			aMap[black[i]] = 1;
		}
	}
	for (int i = 0; i < white.size(); i++)
	{
		// 有了
		if ((iter = wMap.find(white[i])) != wMap.end())
		{
			(iter->second)++;
		}
		else
		{
			wMap[white[i]] = 1;
		}
	}

	// 找最大值
	int result = 0;
	MaxPair amaxp = findMaxPair(aMap);
	MaxPair wmaxp = findMaxPair(wMap);
	if (amaxp.val != wmaxp.val)
	{
		result = black.size() - amaxp.time;
		result += (white.size() - wmaxp.time);
	}
	else
	{
		int a1, b1, a2, b2;
		a1 = wmaxp.time;
		b1 = amaxp.time;
		a2 = findMaxPairEK(aMap, amaxp.val).time;
		b2 = findMaxPairEK(wMap, amaxp.val).time;
		int max = (a1 + b2) > (a2 + b1) ? (a1 + b2) : (a2 + b1);

		result = black.size() + white.size() - max;
	}

	cout << result;
	//system("pause");
	return 0;
}

如有问题还望指出

猜你喜欢

转载自blog.csdn.net/u014573686/article/details/89483333