NSWOJ-2452-这是一道签到题(容斥原理)

题目描述

小唐有一个n×n 块的农田,有一天,小唐往农田里面播散种子,但是农田太大了,小唐只能用无人机来播撒种子。无人机一次只能给一行或者一列播撒种子并且每次给每块农田播撒的种子个数是一样的。经过几次播撒后,小唐知道了每块农田的种子数,但是发现其中有一块农田的种子被小鸟吃完了。小唐想知道如果没有小鸟,这块农田的种子个数是多少。

刚开始所有农田的种子数为0,n次播撒后被小鸟吃光的农田的种子数用-1来表示。

输入

第一行包含一个整数n(2<=n <= 50) 

接下来n行,每行有n个整数 ,代表每块农田的种子数(每个整数范围是[1,50]); 

输出

输出

仅一个整数表示代表被小鸟吃光种子的农田原本的种子数。

样例输入

2
5 8
-1 6

样例输出

3

分析:我们可以把麦田看作是一个矩阵,先找到被吃掉的那一块,我们可以列举如下例子,如图

                                   

我们利用样例数据来解决此题

如果A为-1,而B和C和D又大于零,那么BD行、CD列肯定是被播洒过种子的,且D这块麦田上的种子数是BD和CD列播撒种子数的总和,但B点种子数和C点种子数总和大于D点种子数总和,那么剩下的种子一定是,AC行、AB列播撒种子数的总和。而AC行、AB列同时又是行和列的交点,那么A点种子数一定等于AC行、AB列播撒种子数的总和。得到以下规律,我们可以推出公式Sa=Sb+Sc-Sd。当我们知道A点我们在找到位于对角线的D点,同行的相邻点C,同列的相邻点B。这样就可以求出A点种子数量,但要注意一点,当点A位于顶点或边界时。就要特殊考虑一下再计算结果。

#include<stdio.h>
const int M=5e1+5;
int n,a[M][M],i,j,k,tx,ty,sn,sx,sy;
int main()
{
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=n;j++)
		{
			scanf("%d",&a[i][j]);//输入点 
			if(a[i][j]==-1)
			{
				tx=i,ty=j;//记录特殊点A 
			}
		}
	}
	//以下是点所处的各种位置 
	if(tx==1&&ty==1)
	{//左上 
		sn=a[tx+1][ty+1],sx=a[tx+1][ty],sy=a[tx][ty+1];
	}
	else if(tx==1&&ty==n)
	{//右上 
		sn=a[tx+1][ty-1],sx=a[tx+1][ty],sy=a[tx][ty-1];
	}
	else if(tx==n&&ty==1)
	{//左下 
		sn=a[tx-1][ty+1],sx=a[tx-1][ty],sy=a[tx][ty+1];
	}
	else if(tx==n&&ty==n)
	{//右下 
		sn=a[tx-1][ty-1],sx=a[tx-1][ty],sy=a[tx][ty-1];
	}
	else if(tx==1)
	{//左 
		sn=a[tx+1][ty+1],sx=a[tx+1][ty],sy=a[tx][ty+1];
	}
	else if(tx==n)
	{//右 
		sn=a[tx-1][ty-1],sx=a[tx-1][ty],sy=a[tx][ty-1];
	}
	else if(ty==1)
	{//上 
		sn=a[tx+1][ty+1],sx=a[tx+1][ty],sy=a[tx][ty+1];
	}
	else if(ty==n)
	{//下 
		sn=a[tx-1][ty-1],sx=a[tx-1][ty],sy=a[tx][ty-1];
	}
	else
	{//正常情况 
		sn=a[tx+1][ty+1],sx=a[tx+1][ty],sy=a[tx][ty+1];
	}
	printf("%d\n",sx+sy-sn) ;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值