为什么我的程序在删除下面代码中的注释后会出现运行时错误?
Why does my program give runtime error after removing the comments in the code below?
有一块有植物的田地——一个有 N 行(编号 1 到 N)和 M 列(编号 1 到 M)的网格;在它的 NM 细胞中,K 细胞包含植物,而其余的包含杂草。在这个格子之外,到处都是杂草。如果两个单元格有公共边,则它们是相邻的。
您想在田间建造围栏,使每个包含植物的单元格都满足以下条件:
可以在不穿过任何栅栏的情况下从这个单元格移动到每个包含植物的相邻单元格
不穿过任何栅栏就不可能从这个牢房移动到任何有杂草的牢房
输入:
输入的第一行包含一个整数 T,表示测试用例的数量。 T 测试用例的描述如下。
每个测试用例的第一行包含三个 space 分隔的整数 N、M 和 K。
K线跟随。每行包含两个 space 分隔的整数 r 和 c,表示第 r 行和第 c 列中的单元格包含植物。
#include <iostream>
#include<vector>
#include<queue>
using namespace std;
int main() {
// your code goes here
int t,n,m,i,j,k,flag=0;
int r[4] = {-1,1,0,0};
int c[4] = {0,0,-1,1};
cin>>t;
while(t--) {
int ans=0;
cin>>n>>m>>k;
vector < vector<int> > vec(n, vector<int>(m,0));
/* for(int z=0; z<k; z++) {
cin>>i>>j;
vec[i-1][j-1] = 1;
} */
queue<pair<int,int>> q;
for(i=0;i<n;i++) {
for(j=0;j<m;j++) {
if(vec[i][j] == 1) {
q.push(make_pair(i,j));
flag = 1;
break;
}
}
if(flag==1)
break;
}
while(!q.empty()) {
pair<int,int> p = q.front();
int a = p.first;
int b = p.second;
int x=0;
q.pop();
for(i=0;i<4;i++) {
for(j=0;j<4;j++) {
int rr = a + r[i];
int cc = b + c[j];
if(rr<0 || cc<0 || rr>=n || cc>=m || vec[rr][cc]==0)
continue;
else {
q.push(make_pair(rr,cc));
x++;
}
}
}
ans = ans + (4-x);
}
cout<<ans<<endl;
}
return 0;
}
如果我删除上面的注释,它会显示超时错误。我无法检测到上述语句的问题。
假设用户为 (6, 7) 和 (7, 7) 对都设置了 1。
然后会发生以下情况:
- 第一对被发现是 (6, 7)
- 对于 (6, 7) 对,将 (7, 7) 对添加到队列中
- 对于 (7, 7) 对,将再次添加 (6, 7) 对(但之前已删除)
- 对于 (6, 7) 对,将再次添加 (7, 7) 对
- ...
因此,如果只有一对相邻对,您的循环将永远不会终止(并且问题会随着更大的组而变得更糟)。
如果您想避免这种情况,您可以在访问该字段后设置 vec[rr][cc] = 0
;或者,您可以设置 vec[rr][cc] = -1
(或不同于 0 和 1 的任何其他值),然后您可以区分:1、未访问的 0(但具有相同的值)、已访问的 0(更改为 -1)。不过,您需要调整支票:
if(0 <= rr && rr < n && 0 <= cc && cc < m && vec[rr][cc] == 1)
// ...
因为跳过 == 0
将不再有效(不需要重新排序比较,但现在的方式类似于更接近的数学方程式 0 <= rr <= n
,当然, 在 C++ 中不能这样写)。
有一块有植物的田地——一个有 N 行(编号 1 到 N)和 M 列(编号 1 到 M)的网格;在它的 NM 细胞中,K 细胞包含植物,而其余的包含杂草。在这个格子之外,到处都是杂草。如果两个单元格有公共边,则它们是相邻的。
您想在田间建造围栏,使每个包含植物的单元格都满足以下条件:
可以在不穿过任何栅栏的情况下从这个单元格移动到每个包含植物的相邻单元格 不穿过任何栅栏就不可能从这个牢房移动到任何有杂草的牢房
输入:
输入的第一行包含一个整数 T,表示测试用例的数量。 T 测试用例的描述如下。 每个测试用例的第一行包含三个 space 分隔的整数 N、M 和 K。 K线跟随。每行包含两个 space 分隔的整数 r 和 c,表示第 r 行和第 c 列中的单元格包含植物。
#include <iostream>
#include<vector>
#include<queue>
using namespace std;
int main() {
// your code goes here
int t,n,m,i,j,k,flag=0;
int r[4] = {-1,1,0,0};
int c[4] = {0,0,-1,1};
cin>>t;
while(t--) {
int ans=0;
cin>>n>>m>>k;
vector < vector<int> > vec(n, vector<int>(m,0));
/* for(int z=0; z<k; z++) {
cin>>i>>j;
vec[i-1][j-1] = 1;
} */
queue<pair<int,int>> q;
for(i=0;i<n;i++) {
for(j=0;j<m;j++) {
if(vec[i][j] == 1) {
q.push(make_pair(i,j));
flag = 1;
break;
}
}
if(flag==1)
break;
}
while(!q.empty()) {
pair<int,int> p = q.front();
int a = p.first;
int b = p.second;
int x=0;
q.pop();
for(i=0;i<4;i++) {
for(j=0;j<4;j++) {
int rr = a + r[i];
int cc = b + c[j];
if(rr<0 || cc<0 || rr>=n || cc>=m || vec[rr][cc]==0)
continue;
else {
q.push(make_pair(rr,cc));
x++;
}
}
}
ans = ans + (4-x);
}
cout<<ans<<endl;
}
return 0;
}
如果我删除上面的注释,它会显示超时错误。我无法检测到上述语句的问题。
假设用户为 (6, 7) 和 (7, 7) 对都设置了 1。
然后会发生以下情况:
- 第一对被发现是 (6, 7)
- 对于 (6, 7) 对,将 (7, 7) 对添加到队列中
- 对于 (7, 7) 对,将再次添加 (6, 7) 对(但之前已删除)
- 对于 (6, 7) 对,将再次添加 (7, 7) 对
- ...
因此,如果只有一对相邻对,您的循环将永远不会终止(并且问题会随着更大的组而变得更糟)。
如果您想避免这种情况,您可以在访问该字段后设置 vec[rr][cc] = 0
;或者,您可以设置 vec[rr][cc] = -1
(或不同于 0 和 1 的任何其他值),然后您可以区分:1、未访问的 0(但具有相同的值)、已访问的 0(更改为 -1)。不过,您需要调整支票:
if(0 <= rr && rr < n && 0 <= cc && cc < m && vec[rr][cc] == 1)
// ...
因为跳过 == 0
将不再有效(不需要重新排序比较,但现在的方式类似于更接近的数学方程式 0 <= rr <= n
,当然, 在 C++ 中不能这样写)。