题目
思路
朴实的思路:每次找一个和为负数的,并翻转。死循环?
不要害怕死循环。注意到每次翻转时,矩阵内所有元素的和都在变大。一次至少变大 2 2 2 。于是复杂度 O [ n m a ( n + m ) ] \mathcal O[nma(n+m)] O[nma(n+m)] ,这是最坏情况。应该是卡不到。
代码
#include <cstdio>
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
inline int readint(){
int a = 0; char c = getchar(), f = 1;
for(; c<'0'||c>'9'; c=getchar())
if(c == '-') f = -f;
for(; '0'<=c&&c<='9'; c=getchar())
a = (a<<3)+(a<<1)+(c^48);
return a*f;
}
template < typename T >
void getMax(T&a,const T&b){if(a<b)a=b;}
template < typename T >
void getMin(T&a,const T&b){if(b<a)a=b;}
const int MaxN = 105;
int row[MaxN], col[MaxN], a[MaxN][MaxN];
int ansr[MaxN], ansc[MaxN], n, m;
int main(){
n = readint(), m = readint();
for(int i=1; i<=n; ++i)
for(int j=1; j<=m; ++j){
a[i][j] = readint();
row[i] += a[i][j];
col[j] += a[i][j];
}
while(true){
bool ok = true;
for(int i=1; i<=n; ++i)
if(row[i] < 0){
ok = false;
for(int j=1; j<=m; ++j){
col[j] -= a[i][j]<<1;
a[i][j] -= a[i][j]<<1;
}
row[i] -= row[i]<<1;
ansr[i] ^= 1;
}
for(int j=1; j<=m; ++j)
if(col[j] < 0){
ok = false;
for(int i=1; i<=n; ++i){
row[i] -= a[i][j]<<1;
a[i][j] -= a[i][j]<<1;
}
col[j] -= col[j]<<1;
ansc[j] ^= 1;
}
if(ok) break;
}
int R = 0, C = 0;
for(int i=1; i<=n; ++i)
R += ansr[i];
for(int i=1; i<=m; ++i)
C += ansc[i];
printf("%d",R);
for(int i=1; i<=n; ++i)
if(ansr[i]) printf(" %d",i);
printf("\n%d",C);
for(int i=1; i<=m; ++i)
if(ansc[i]) printf(" %d",i);
putchar('\n'); return 0;
}