codeforces 226D The table(贪心+构造)

D. The table
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Harry Potter has a difficult homework. Given a rectangular table, consisting of n × m cells. Each cell of the table contains the integer. Harry knows how to use two spells: the first spell change the sign of the integers in the selected row, the second — in the selected column. Harry's task is to make non-negative the sum of the numbers in each row and each column using these spells.

Alone, the boy can not cope. Help the young magician!

Input

The first line contains two integers n and m (1 ≤ n,  m ≤ 100) — the number of rows and the number of columns.

Next n lines follow, each contains m integers: j-th integer in the i-th line is ai, j (|ai, j| ≤ 100), the number in the i-th row and j-th column of the table.

The rows of the table numbered from 1 to n. The columns of the table numbered from 1 to m.

Output

In the first line print the number a — the number of required applications of the first spell. Next print a space-separated integers — the row numbers, you want to apply a spell. These row numbers must be distinct!

In the second line print the number b — the number of required applications of the second spell. Next print b space-separated integers — the column numbers, you want to apply a spell. These column numbers must be distinct!

If there are several solutions are allowed to print any of them.

Examples
input
4 1
-1
-1
-1
-1
output
4 1 2 3 4 
0 
input
2 4
-1 -1 -1 2
1 1 1 1
output
1 1 
1 4 


题目大意:给出一个矩阵,每次可以选择反转行或列,求一种合法的方案使最终的矩阵所有行的权值和和列的权值和分别大于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");
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值