题目描述
给你一个N*M 的矩阵,矩阵里面的元素要么是正数,要么是负数,它们的绝对值不大
于10000。现在你可以对矩阵进行两种操作:
1、将某一列的元素全部取反。
2、将某一行的元素全部取反。
你可以执行任意次操作。
Task:通过以上两种操作如果可以将整个矩阵的元素全变为正数的话,则输出最少的操
作次数,否则输出“impossible”(不包括双引号)。
Input
输入文件的第一行有两个整数n 和m(1≤n,m≤1000),表示矩阵的大小。
接下来有N 行,每行M 个数,每个数之间有一个空格。
Output
通过以上两种操作如果可以将整个矩阵的元素全变为正数的话,则输出最少的操作次
数,否则输出“impossible”(不包括双引号)。
Sample Input
2 4
3 7 -6 1
-2 -6 8 -4
Sample Output
2
Hint
对于100%的数据,2≤N,M≤1000
分析
矩阵题真神奇系列
枚举行,判断该行负数多还是少
多的直接反了这一行
少的逐列取反
同时做优化:如果某行或某列反了两次或以上,必定impossible
(这程序好像不是AC标程呢)
#include <iostream>
#include <cstdio>
#define rep(i,a,b) for (i=a;i<=b;i++)
using namespace std;
int n,m;
int a[1001][1001];
int rc[1001],cc[1001];
int zfr[1001],zfc[1001];
int i,j;
int f,z;
int ans;
int main()
{
// freopen("matrix.in","r",stdin);
// freopen("matrix.out","w",stdout);
scanf("%d%d",&n,&m);
rep(i,1,n)
{
rep(j,1,m)
{
scanf("%d",&a[i][j]);
zfc[j]=1;
}
zfr[i]=1;
}
rep(i,1,n)
{
f=z=0;
rep(j,1,m)
if (a[i][j]*zfr[i]*zfc[j]<0) f++; else z++;
if (f<z)
rep(j,1,m)
if (a[i][j]*zfr[i]*zfc[j]<0)
{
zfc[j]=-zfc[j];
cc[j]++;
if (cc[j]==2)
{
printf("impossible");
return 0;
}
ans++;
}
if (f>=z)
{
zfr[i]=-zfr[i];
rc[i]++;
if (rc[i]==2)
{
printf("impossible");
return 0;
}
ans++;
}
}
printf("%d",ans);
}