Educational Codeforces Round 71 (Rated for Div. 2)——B:Square Filling(贪心)

题目描述:

题目传送门:http://codeforces.com/contest/1207/problem/B

题目大意:两个值只能为0或1的矩阵,矩阵A是给定的,矩阵B是全为0的。当我们把b[i][j]置1的时候,b[i+1] [j] , b[i] [j+1] , b[i+1] [j+1]都要置1。问翻转几次并且翻转哪几个块能使矩阵A变换为矩阵B。如果矩阵A无法通过变换得到矩阵B,输出-1。如果矩阵A也是全0的(A,B的初始状态相同),输出0。

解题思路:

主要思想还是贪心思想。对A进行遍历,如果A【i】【j】且与它相邻的3个点都是1,且B【i】【j】以及其相邻的三个点(共四个点)中至少有一个不为1(因为都为1就没必要再翻了)。那么就翻转B【i】【j】,以及它相邻的3个点,用数组X和数组Y分别记录所翻转的点的横、纵坐标,需要注意的是坐标是从1开始的,所以记录的实际上是i+1和j+1的值。再定义一个tot变量来记录一下一共需要翻几次。用flag来判断能否最终翻成A。

AC代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int main()
{
	int c=0,d=0,flag=0,n=0,m=0,tot=0,count=0;
	cin>>n>>m;
	int a[n][m];
	memset(a,0,sizeof(a));
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			cin>>a[i][j];
	int b[n][m];
	memset(b,0,sizeof(b));
	int x[2505]={0},y[2505]={0};//这个数组的范围一定要注意,不然会超时
	//原来的范围是55,结果test5一直超时,后来迷过来了,一共是2500个点而不是50个
	//但是为什么会超时呢? 
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			if(a[i][j]==0)
			{
				count++;
			}
		}
		
	}
	if(count==n*m)
	{
		cout<<0<<endl;
		return 0;
	}
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			if(a[i][j]==1&&a[i+1][j]==1&&a[i][j+1]==1&&a[i+1][j+1]==1&&(b[i][j]==0||b[i+1][j]==0||b[i][j+1]==0||b[i+1][j+1]==0)&&i+1<n&&j+1<m)//注意i+1和j+1的范围
			{
				b[i][j]=1;
				b[i+1][j]=1;
				b[i][j+1]=1;
				b[i+1][j+1]=1;
				x[c]=i+1;
				y[c]=j+1;
				c++;
			//	d++;
				tot++;
			}
		}
	}
	for(int i=0;i<n;i++)
		{
			for(int j=0;j<m;j++)
			{
				if(a[i][j]!=b[i][j])
				{
					flag=1;
				}
			}
		
		}
	if(flag==0)
	{
		cout<<tot<<endl;
		for(int i=0;i<c;i++)
		cout<<x[i]<<" "<<y[i]<<endl;	
	}	
	if(flag==1)
	cout<<-1<<endl;
	return 0;
}

注意事项:

x,y数组的范围一定要给够,要给到2500(实际上用不了那么多),刚开始我给的一直是55……太迷了,超时了好几次不知道原因在哪里。然后就是在判断条件里面,一定别忘了对i+1和j+1的范围做一个限定,分别是小于n和m的,不然会造成数组越界

还有一个疑问,就是为什么我的x,y数组范围给的不够的时候错误原因是超时呢?希望评论区的大神可以帮忙解答一下这个问题。

问题解答:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值