牛客寒假训练营 3 C 牛牛的数组越位

题目要求

链接:https://ac.nowcoder.com/acm/contest/3004/C
来源:牛客网

牛牛写了这样一个C/C++程序:

#include<bits/stdc++.h>
using namespace std;
int main()
{
int a[5][5];
a[-1][8]=12345;
printf("%d %d",a[1][-2],a[0][3]);
return 0;
}

他发现程序可以正常运行,并且输出为:

12345 12345

在C/C++中,这种数组越位行为是Undefined Behaviour(UB)的,也就是程序未定义行为,但是在牛牛的编译器呢,对于这种情况,二维数组的内存是连续的。
也就是说对于二维数组int a[5][5],在牛牛的电脑中是按照a[0][0],a[0][1],a[0][2],a[0][3],a[0][4],a[1][0]…a[1][4],a[2][0]…a[2][4],a[3][0]…a[4][4]
这样储存的。
牛牛所使用的编译器在寻址时是这样处理的,对于一个二维数组a[n][m],若对a[x][y]这个数组元素进行操作,最终访问到的地址为:a的首地址+m*x+y。
所以在寻址时,无论是a[-1][8]还是a[1][-2]最终在牛牛的电脑上使用该编译器编译出的程序均未发生非法访问的行为,他们最终都表示a[0][3]这个数组元素。

本题有T组测试数据。

牛牛先声明了一个n*m的int 型数组,即int a[n][m];,这个数组被他声明成一个全局变量,所以数组的初值全为0,接下来他要进行p次赋值运算。
每次他都选择一个二维下标x,y,并且把a[x][y]赋值成val。
当然,牛牛不会老老实实按照C语言的规范来写代码。

如果这p次赋值操作中不存在数组越位行为,则先输出n行,每行m个数。表示操作后的二维数组,数字之间用一个空格隔开,行末没有多余空格。然后输出一行"Accepted"(不含引号),表示正常运行。

如果这p次赋值操作中虽然存在数组越位行为但是没有发生非法访问,则先输出n行,每行m个数。表示操作后的二维数组,数字之间用一个空格隔开,行末没有多余空格。然后输出一行"Undefined Behaviour"(不含引号),表示虽然能够运行,但是牛牛的代码不规范存在隐患。

如果这p次赋值操作中出现了至少一次数组越位并且导致非法访问的行为,请输出一行一个字符串"Runtime error"(不含引号)。
输入描述:

第一行是一个正整数T(1≤T≤1000)(1 \leq T \leq 1000)(1≤T≤1000)表示测试样例的组数且保证∑n×m≤2×107且∑p≤2×107\sum n \times m \leq 2 \times 10^7且 \sum p \leq 2 \times 10^7∑n×m≤2×107且∑p≤2×107。对于每组案例:

第一行是三个正整数n,m,p(1≤n,m≤1000,0≤p≤10000)(1 \leq n,m \leq 1000,0 \leq p \leq 10000)(1≤n,m≤1000,0≤p≤10000)表示牛牛在全局中声明了一个int型的a数组,即int a[n][m];,接下来牛牛准备进行p次赋值操作。

接下来p行,每行三个整数x,y,val(−1000000≤x,y,val≤1000000)(-1000000 \leq x,y,val \leq 1000000)(−1000000≤x,y,val≤1000000)表示进行一次赋值操作,即a[x][y]=val;。

输出描述:

如果这p次赋值操作中不存在数组越位行为,则先输出n行,每行m个数。表示操作后的二维数组,数字之间用一个空格隔开,行末没有多余空格。然后输出一行"Accepted"(不含引号),表示正常运行。

如果这p次赋值操作中虽然存在数组越位行为但是没有发生非法访问,则先输出n行,每行m个数。表示操作后的二维数组,数字之间用一个空格隔开,行末没有多余空格。然后输出一行"Undefined Behaviour"(不含引号),表示虽然能够运行,但是牛牛的代码不规范,存在隐患。

如果这p次赋值操作中出现了至少一次数组越位并且导致非法访问的行为,请输出一行一个字符串"Runtime error"(不含引号)。

示例1
输入
复制

4
2 4 8
-1 4 1
1 -3 2
2 -6 3
0 3 4
-1 8 5
-2 13 6
-100 406 7
100 -393 8
5 5 1
-1 8 1234
10 10 1
5 -51 1
1 1 1
0 0 7

输出
复制

1 2 3 4
5 6 7 8
Undefined Behaviour
0 0 0 1234 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
Undefined Behaviour
Runtime error
7
Accepted

备注:

无论是否发生数组越位或者非法访问,输入数据都要完整读入。
题目中的代码不符合C/C++规范,在不同编译器中由于实现不同运行的结果也可能不同,请勿依赖特定编译器对于UB的实现。😃

解题思路

这个题不难,只要理解了题目让你干什么,就很好解。显然,现在二维数组的x和y有3种情况:第一种,x和y分别在0-n和0-m以内,Ac;第二种:虽然x和y分别不在0-n和0-m以内,但是xm+y>=0&&xm+y<n*m,Ub;第三种:除了以上两种情况的任何一种情况,Re:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e6+10;
ll a[maxn];
int main(){
         int t,n,m,p;
         ll x,y,val;
         scanf("%d",&t);
         while(t--){
               int flag1=0,flag2=0;
               scanf("%d%d%d",&n,&m,&p);
               for(int i=0;i<n*m;i++){
                              a[i]=0;
               }
               while(p--){
                        scanf("%lld%lld%lld",&x,&y,&val);
                        ll au=x*m+y;
                        if(x>=0&&x<n&&y>=0&&y<m)
                              a[au]=val;
                        else if(au>=0&&au<n*m){
                              a[au]=val;
                              flag2=1;
                        }
                        else
                              flag1=1;
               }
               if(!flag1){
                              for(int i=0;i<n*m;i++){
                                             printf("%lld ",a[i]);
                                             if((i+1)%m==0)
                                                            printf("\n");
                              }
                              if(flag2)
                                             printf("Undefined Behaviour\n");
                              else
                                             printf("Accepted\n");
               }
               else
                              printf("Runtime error\n");
         }
         return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值