问题描述
- 给一个两行的矩阵,要求最大的MEX值
- MEX值是指在所选的几列中未出现值的最小值
- 那么假设所选几列中既有1又有0的话他的MEX就是2,依此类推
思路分析
- 首先,我们先找出矩阵中既有
0
0
0又有
1
1
1的那一列,因为他的贡献为
2
2
2,并且我们需要把这样的列单独拿出来(使得答案最大)
- 在进行上一步操作后,所剩下的列就是只有
00
00
00和
11
11
11的了,那么对于单独的
00
00
00,他的贡献显然为
1
1
1,单独的
11
11
11,他的贡献显然为
0
0
0,那么对于两列呢?
- 如果我们能找到相邻两列分别只有
0
0
0,
1
1
1的话,我们就选上,这样的话不会浪费
00
00
00列,并且比两列单独取的值更大
- 所以我们在进行第一步操作后,应再跑一遍矩阵,找到相邻的
00
00
00,
11
11
11对,在这里,我用的是vis数组,表明该列已经被使用,这样的话能确保不会选上之前选出来的
00
00
00或者
11
11
11,当然还有
01
01
01,
10
10
10。
- 那么还有遗漏就是,把所有的
01
01
01,
10
10
10挑出来,再把所有
11
11
11匹配后
00
00
00还有剩的话,我们需要再跑一边矩阵,找到那个未被使用的
00
00
00列的个数,加上贡献即可
代码如下
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int vis[maxn];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
{
memset(vis, 0, sizeof(vis));
int n;
cin >> n;
string s1, s2;
cin >> s1;
cin >> s2;
int sum = 0;
for (int i = 0; i < n; i++)
{
if ((s1[i] == '0' && s2[i] == '1') || (s1[i] == '1' && s2[i] == '0'))
{
sum += 2;
vis[i] = 1;
}
}
for (int i = 0; i < n; i++)
{
if (vis[i])
{
continue;
}
if (s1[i] == '1' && s2[i] == '1')
{
if (i >= 1 && vis[i - 1] != 1 && (s1[i - 1] == '0' && s2[i - 1] == '0'))
{
sum += 2;
vis[i] = 1;
vis[i - 1] = 1;
}
else if (i <= n - 2 && vis[i + 1] != 1 && (s1[i + 1] == '0' && s2[i + 1] == '0'))
{
sum += 2;
vis[i] = 1;
vis[i + 1] = 1;
}
}
}
for (int i = 0; i < n; i++)
{
if (!vis[i] && (s1[i] == '0' && s2[i] == '0'))
{
sum++;
}
}
cout << sum << endl;
}
return 0;
}