题目大意:给出一个矩阵,每次可以选择反转行或列,求一种合法的方案使最终的矩阵所有行的权值和和列的权值和分别大于0。
这道题可以每次贪心的选取权值为负的行或列,然后将这一行或列中的每个数取他的相反数。
需要注意到是,这道题在输出的时候只输出翻转次数为奇数次的行或列。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 103
using namespace std;
int a[N][N],m,n;
int h[N],l[N],markh[N],markl[N];
int find()
{
for (int i=1;i<=n;i++)
if (h[i]<0) return i;
return 0;
}
int find1()
{
for (int i=1;i<=m;i++)
if (l[i]<0) return i;
return 0;
}
int main()
{
//freopen("a.in","r",stdin);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
h[i]+=a[i][j];
l[j]+=a[i][j];
}
int t=0,t1=0;
while ((t=find())||(t1=find1()))
{
if (t){
markh[t]++; int sum=0;
for (int i=1;i<=m;i++)
{
int k=-a[t][i];
l[i]=l[i]-a[t][i]+k;
a[t][i]=k; sum+=k;
}
h[t]=sum;
}
else {
markl[t1]++; int sum=0;
for (int i=1;i<=n;i++)
{
int k=-a[i][t1];
h[i]=h[i]-a[i][t1]+k;
a[i][t1]=k; sum+=k;
}
l[t1]=sum;
}
}
int num=0,num1=0;
for (int i=1;i<=n;i++) if (markh[i]&1) num++;
printf("%d ",num);
for (int i=1;i<=n;i++)
if (markh[i]&1) printf("%d ",i);
printf("\n");
for (int i=1;i<=m;i++) if (markl[i]&1) num1++;
printf("%d ",num1);
for (int i=1;i<=m;i++)
if (markl[i]&1) printf("%d ",i);
printf("\n");
}