有一个n*m的矩阵,每次可以将一列取负或者将一行取负,求一个方案使得每行每列的和都非负。
n,m<=100,元素绝对值<=100
如果有某一行或某一列为负 直接取反
这样整个矩阵的和肯定会变大 也就是说一定结束
每次操作至少使和增加
2
,而和最大
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int N=105;
int n,m;
int a[N][N];
int sr[N],sc[N];
int r[N],c[N];
#define read(x) scanf("%d",&(x))
int main(){
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(m);
for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) read(a[i][j]),sr[i]+=a[i][j],sc[j]+=a[i][j];
while (1){
int k=0;
for (int i=1;i<=n;i++) if (sr[i]<0) { k=i; break; }
if (k){
sr[k]=-sr[k]; r[k]^=1;
for (int j=1;j<=m;j++)
sc[j]-=a[k][j]<<1,a[k][j]=-a[k][j];
continue;
}
k=0;
for (int j=1;j<=m;j++) if (sc[j]<0) { k=j; break; }
if (k){
sc[k]=-sc[k]; c[k]^=1;
for (int i=1;i<=n;i++)
sr[i]-=a[i][k]<<1,a[i][k]=-a[i][k];
continue;
}
break;
}
int tot=0;
for (int i=1;i<=n;i++) tot+=r[i];
printf("%d ",tot);
for (int i=1;i<=n;i++) if (r[i]) printf("%d ",i); printf("\n");
tot=0;
for (int j=1;j<=m;j++) tot+=c[j];
printf("%d ",tot);
for (int j=1;j<=m;j++) if (c[j]) printf("%d ",j); printf("\n");
return 0;
}