
我的思路:
把每一组的每一个字符对应存下来,没有的为 0。样例的话就是
A-1 B-0 C-3
A-2 B-0 C-1
A-0 B-3 C-1
把数字组成一个矩阵,并且给每一行(每一个数据)一个编号:
1. 1 0 3
2. 2 0 1
3. 0 3 1
将每两个数据组成的数串匹配。 对与两个数据的每一位上来说,如果有一个是 0 或者他们是相等的就匹配(没出现的可以是任何字符)。所以 2. 和 3. 是匹配的
这个时候,我们将两两匹配的数据之间连一条边,组成一个图。即 2 和 3之间连一条边。
然后,在这个图上,我们找到最大的完全子图(最大团问题),可以用匈牙利算法,但我这里用的是专门解决这个问题的算法(忘了叫啥了,但是正确的)。
我的样例过了,请求哪个大佬救救我了,给个 hack 也行。。。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e2 + 10;
int graph[maxn][maxn];
bool nwx[maxn], bestx[maxn];
int bestn;
int n, m, s;
bool place(int x) {
for (int i = 1; i < x; ++i)
if (nwx[i] && !graph[x][i]) return false;
return true;
}
void backtrack(int x) {
if (x > n) {
for (int i = 1; i <= n; ++i) bestx[i] = nwx[i];
bestn = s;
return;
}
if (place(x)) {
nwx[x] = 1, s++;
backtrack(x + 1);
s--;
}
if (s + n - x > bestn) {
nwx[x] = 0;
backtrack(x + 1);
}
}
void Max_Clique() {
backtrack(1);
cout << bestn << '\n';
//for (int i = 1; i <= n; ++i) if (bestx[i]) cout << i << ' ';
}
int N, M;
int f[maxn][maxn];
bool ifMate(int x, int y) {
for (int i = 1; i <= N; ++i)
if (f[x][i] != f[y][i] && f[x][i] != 0 && f[y][i] != 0) return false;
return true;
}
bool vis[maxn];
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> N >> M;
string s;
for (int i = 1, len; i <= M; ++i) {
cin >> s;
len = s.size();
for (int j = 1, x, a; j <= len; ++j) {
cin >> a;
x = (s[j - 1] - 'A' + 1);
f[i][x] = a;
}
}
for (int i = 1; i <= N; ++i)
for (int j = i + 1; j <= N; ++j) {
if (!ifMate(i, j)) continue;
graph[i][j] = graph[j][i] = 1;
}
n = N;
// for (int i = 1; i <= N; ++i) {
// for (int j = 1; j <= N; ++j) cout << f[i][j] << ' ';
// cout << '\n';
// }for (int i = 1; i <= N; ++i) {
// for (int j = 1; j <= N; ++j) cout <<graph[i][j] << ' ';
// cout << '\n';
// }
Max_Clique();
}