【COCI 2018/2019 Round #2】Kocka

这道题也是一个ex的模拟题

不过他比Zamjena可爱

在这里插入图片描述
作为一个帅气的小哥哥,让我们一起,
开启你的模拟ex大门,C++从入门到放弃!

题目

题目描述
我又来了!我又来了!
在清晨来到儿童游乐园的时候,出题人看到了一些有趣的物体:这些物体是由金属棒组成的大小不一的立方体。

在观察这些立方体的时候,出题人想到了一个有趣的问题,下面是这个问题的二维版本(因为没有人喜欢涉及三维对象的问题):你得到一个n*n的矩形(参考正方形),矩形中的一些方格是空的,有些不是。出题人从四面八方查看这个矩形,首先,他从矩形的左边开始看,记录下第一个不为空的方格的前面有多少个空格,如果这一行没有非空方格,则记录为-1。然后,他重复前面的操作,从右边,上面和下面观察这个矩形,这样,他得到了4n个这样的数字(每个边记录n个数字),然而,某个未知恶魔破坏了这个矩形,只留下了出题人留下的数字。出题人想知道,留下的这些数字是否有意义,即通过这些数字,是否能够组成一个正方形。

输入格式
第一行包含正整数n(1≤n≤100000),表示这个正方形的边长。
第二行输入n个数字Li(-1≤Li<n),表示从左边观察时第一个到第n个数字。
第三行输入n个数字Ri(-1≤Ri<n),表示从右边观察时第一个到第n个数字。
第四行输入n个数字Ui(-1≤Ui<n),表示从上边观察时第一个到第n个数字。
第五行输入n个数字Di(-1≤Di<n),表示从下边观察时第一个到第n个数字。
输出格式
如果这些数字能组成一个正方形,输出“DA”,否则输出“NE”

样例
样例输入1
3
-1 2 0
-1 0 1
2 2 1
0 0 1
样例输出1
DA
样例输入2
3
-1 0 1
-1 2 1
-1 2 -1
1 0 -1
样例输出2
NE

题解

既然要输出DA,NE,那肯定是绑点了的,想单纯骗分很考技术!
读完题后肯定知道如果相互矛盾就是NE,不然就是DA,
没有必要去把整个矩阵给模拟构造出来,
只需要去判断四个数组条件是否相互冲突即可

接下来冲突的情况口头上讲解是比较难以理解
可以画一画样例跟着一起推帮助理解

左右,上下冲突的情况:l+r>=n,u+d>=n
证明:只有1个非空点i,那么l应该为i-1,r应该为n-i,相加是n-1,证毕

左与上下,右与上下,上与左右,下与左右,垂直冲突的情况:
以证明左与上下为例:
如果l=-1,那么这一行就都是空,
那么任何一个u,d的非空位置都不能出现在这一行上
可以把这四种情况合成一个for循环完成

因为每一个l,r,u,d是第一个非空的位置-1
这中间可能有很多个非空
我们就只能找到第一个进行判断

代码实现

因为我的代码力。。。
这道题我把n砍成了一半,里面有些许变化

#include <cstdio>
#define MAXN 100005
int n;
int l[MAXN], r[MAXN], u[MAXN], d[MAXN];
bool L[MAXN], R[MAXN], U[MAXN], D[MAXN];
int main() {
	scanf ( "%d", &n );
	for ( int i = 1;i <= n;i ++ )
		scanf ( "%d", &l[i] );
	for ( int i = 1;i <= n;i ++ )
		scanf ( "%d", &r[i] );
	for ( int i = 1;i <= n;i ++ )
		scanf ( "%d", &u[i] );
	for ( int i = 1;i <= n;i ++ )
		scanf ( "%d", &d[i] );
	for ( int i = 1;i <= n;i ++ ) {
		if ( l[i] + r[i] >= n || u[i] + d[i] >= n ) 
			return ! printf ( "NE" );
		if ( l[i] != r[i] && ( l[i] == -1 || r[i] == -1 ) ) 
			return ! printf ( "NE" );
		if ( u[i] != d[i] && ( u[i] == -1 || d[i] == -1 ) ) 
			return ! printf ( "NE" );
	}
	for ( int i = 1;i <= n / 2;i ++ ) {
		if ( l[i] != -1 && u[l[i] + 1] == -1 ) return ! printf ( "NE" );
		if ( r[i] != -1 && u[n - r[i]] == -1 ) return ! printf ( "NE" );
		if ( u[i] != -1 && l[u[i] + 1] == -1 ) return ! printf ( "NE" );
		if ( d[i] != -1 && l[n - d[i]] == -1 ) return ! printf ( "NE" );
		if ( l[i] != -1 && ! L[l[i]] ) {
			L[l[i]] = 1;
			if ( u[l[i] + 1] > i - 1 ) return ! printf ( "NE" );
		}
		if ( r[i] != -1 && ! R[r[i]] ) {
			R[r[i]] = 1;
			if ( u[n - r[i]] > i - 1 ) return ! printf ( "NE" );
		}
		if ( u[i] != -1 && ! U[u[i]] ) {
			U[u[i]] = 1;
			if ( l[u[i] + 1] > i - 1 ) return ! printf ( "NE" );
		}
		if ( d[i] != -1 && ! D[d[i]] ) {
			D[d[i]] = 1;
			if ( l[n - d[i]] > i - 1 ) return ! printf ( "NE" );
		}
	}
	for ( int i = 1;i <= n;i ++ )
		L[i] = R[i] = U[i] = D[i] = 0;
	for ( int i = n;i > n / 2;i -- ) {
		if ( l[i] != -1 && d[l[i] + 1] == -1 ) return ! printf ( "NE" );
		if ( r[i] != -1 && d[n - r[i]] == -1 ) return ! printf ( "NE" );
		if ( u[i] != -1 && r[u[i] + 1] == -1 ) return ! printf ( "NE" );
		if ( d[i] != -1 && r[n - d[i]] == -1 ) return ! printf ( "NE" );
		if ( l[i] != -1 && ! L[l[i]] ) {
			L[l[i]] = 1;
			if ( d[l[i] + 1] > n - i ) return ! printf ( "NE" );
		}
		if ( r[i] != -1 && ! R[r[i]] ) {
			R[r[i]] = 1;
			if ( d[n - r[i]] > n - i ) return ! printf ( "NE" );
		}
		if ( u[i] != -1 && ! U[u[i]] ) {
			U[u[i]] = 1;
			if ( r[u[i] + 1] > n - i ) return ! printf ( "NE" );
		}
		if ( d[i] != -1 && ! D[d[i]] ) {
			D[d[i]] = 1;
			if ( r[n - d[i]] > n - i ) return ! printf ( "NE" );
		}
	}
	printf ( "DA" );
	return 0;
}

我终于A了一道结论题,
在这里插入图片描述
过不了多久,我会再发一篇ex至极的博客,Zamjena,仙女还没A这道题
在这里插入图片描述
有什么问题,欢迎留言,后会有期,bye~~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值