又是一道无链接的题。
现在它是一道有链接的题啦!谢谢青烟dark在评论区指出来源!
当时在考场上画了几张图,思路是将第一行全都统一,再比较列的不同。其实有点像正解,但其实发现,我的做法无法判断第一行有变化的情况(且判断了会超时)。
下见代码。
#include<cstdio>
#include<iostream>
using namespace std;
const int N = 1002;
int n, k, G[N][N], tot1, tot2, tmp, tot;
int main() {
char ch;
scanf("%d %d", &n, &k);
for(int i = 1; i <= n; i ++) {
scanf("\n");
for(int j = 1; j <= n; j ++) {
ch = getchar();
if(ch == 'x')
G[i][j] = 1;
}
}
tmp = k;
for(int i = 1; i <= n; i ++) {
if(G[1][i] != 0) {
for(int j = 1; j <= n; j ++)
G[j][i] = ! G[j][i];
}
}
for(int i = 2; i <= n; i ++) {
tot1 = tot2 = 0;
for(int j = 1; j <= n; j ++)
if(G[i][j] == 0)
tot1 ++;
else
tot2 ++;
tmp -= min(tot1, tot2);
if(tmp < 0) {
tot ++;
break;
}
}
tmp = k;
for(int i = 1; i <= n; i ++) {
if(G[n][i] != 0) {
for(int j = 1; j <= n; j ++)
G[j][i] = ! G[j][i];
}
}
for(int i = 1; i < n; i ++) {
tot1 = tot2 = 0;
for(int j = 1; j <= n; j ++)
if(G[i][j] == 0)
tot1 ++;
else
tot2 ++;
tmp -= min(tot1, tot2);
if(tmp < 0) {
tot ++;
break;
}
}
tmp = k;
for(int i = 1; i <= n; i ++) {
if(G[n - 1][i] != 0) {
for(int j = 1; j <= n; j ++)
G[j][i] = ! G[j][i];
}
}
for(int i = 1; i <= n; i ++) {
if(i == n - 1)
continue;
tot1 = tot2 = 0;
for(int j = 1; j <= n; j ++)
if(G[i][j] == 0)
tot1 ++;
else
tot2 ++;
tmp -= min(tot1, tot2);
if(tmp < 0) {
tot ++;
break;
}
}
if(tot == 3)
printf("NE\n");
else
printf("DA\n");
return 0;
}
然后咧,我发现了个好东西,叫异或。可以大大减低复杂度。其实我们只需再考虑一种情况:n == k。因为当相等时,所有的行都有可能被更改,之前的算法算不出来。故需要枚举一下。
上马!
#include<cstdio>
#include<bitset>
#include<iostream>
using namespace std;
const int N = 1002;
int n, k;
bitset <N> s[N];
int main() {
int tmp, sum;
char ch;
scanf("%d %d", &n, &k);
for(int i = 1; i <= n; i ++) {
scanf("\n");
for(int j = 1; j <= n; j ++) {
ch = getchar();
if(ch == 'o')
s[i].set(j);
}
}
if(n == k) {
bool f;
for(int i = 1; i <= n; i ++) {
s[1].flip(i);
f = 0;
for(int j = 2; j <= n; j ++) {
s[0] = s[1] ^ s[j];
tmp = s[0].count();
if(min(tmp, n - tmp) != 1) {//A
f = 1;
break;
}
}
if(! f)
return ! printf("DA\n");
s[1].flip(i);
}
}
for(int i = 1; i <= n; i ++) {
sum = 0;
for(int j = 1; j <= n; j ++) {
if(j == i)
continue;
s[0] = s[i] ^ s[j];
tmp = s[0].count();
sum += min(tmp, n - tmp);
}
if(sum <= k)
return ! printf("DA\n");
}
printf("NE\n");
return 0;
}
注:
A:所有行修改的情况即每行改1,如有就输出DA。没有也加入后面判断,因为剩下便是至少有一行不更改。
如有错误,请大佬在评论区指出。谢谢!