Description:
题解:
怎么说呢,一道联赛题没有做出来。
以后还是要在一开始就想清楚,后面真的是越想越迷。
首先需要判断答案是否存在,这非常简单,每次找到一行或一列全是一样颜色的,然后把他们变成通配颜色,如果矩阵能全部变成通配颜色,就可行。
不然发现要不每一行都染了,要不每一列都染了,不然会有点染不到。
假设每一行都染了,我们不用关心每一行染了什么,只用看最多有多少列完全相同,行的染色方案去贴合这些列,其它列去贴合行一定是最优的。
n+m-这个即可。
Code:
#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define gc getchar
#define pp printf
#define ul unsigned long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;
char get() {
char c = ' ';
while(c != 'B' && c != 'R') c = gc();
return c;
}
const int N = 3005;
int ct;
int n, m, a[N][N], b[N][N];
int pd() {
fo(i, 1, n) fo(j, 1, m) if(a[i][j] != 0) return 0;
return 1;
}
int s1[N][3], s2[N][3];
int pdd() {
int q0 = 1;
fo(i, 1, n) {
if(s1[i][0] == m) continue;
q0 = 0;
if(s1[i][1] && s1[i][2]) continue;
fo(j, 1, m) {
s1[i][a[i][j]] --;
s2[j][a[i][j]] --;
a[i][j] = 0;
s1[i][a[i][j]] ++;
s2[j][a[i][j]] ++;
}
return pdd();
}
fo(j, 1, m) {
if(s2[j][0] == n) continue;
q0 = 0;
if(s2[j][1] && s2[j][2]) continue;
fo(i, 1, n) {
s1[i][a[i][j]] --;
s2[j][a[i][j]] --;
a[i][j] = 0;
s1[i][a[i][j]] ++;
s2[j][a[i][j]] ++;
}
return pdd();
}
return q0;
}
map<ul, int> bz;
int main() {
freopen("square.in", "r", stdin);
freopen("square.out", "w", stdout);
scanf("%d %d", &n, &m);
fo(i, 1, n) fo(j, 1, m) a[i][j] = get() == 'B' ? 1 : 2;
fo(i, 1, n) fo(j, 1, m) s1[i][a[i][j]] ++, s2[j][a[i][j]] ++;
fo(i, 1, n) fo(j, 1, m) b[i][j] = a[i][j];
if(!pdd()) {
pp("-1\n");
return 0;
}
fo(i, 1, n) fo(j, 1, m) a[i][j] = b[i][j];
int mx = 0;
fo(i, 1, n) {
ul sum = 0, x = 1;
fo(j, 1, m) sum += x * a[i][j], x *= 23;
bz[sum] ++;
mx = max(mx, bz[sum]);
}
bz.clear();
fo(j, 1, m) {
ul sum = 0, x = 1;
fo(i, 1, n) sum += x * a[i][j], x *= 23;
bz[sum] ++;
mx = max(mx, bz[sum]);
}
pp("%d", n + m - mx);
}