如何解决对于SPOJ WATER问题,SIGABRT错误背后的原因可能是什么?
我下面的SPOJ WATER Problem代码在ideone,glot和本地运行良好,但是在提交解决方案时却出现SIBABRT运行时错误。
我的解决方案虽然没有经过优化,但大致遵循以下算法
- 基于最小高度/高度对图进行排序。
- 遍历排序的图,并一一到达最小节点并执行3和4。
- 用最小围墙值填充节点
- FloodFill:在3中以最少的围墙填充新级别/高度的整个表面(多个节点)。
- 如果超出区域或发现任何下表面,则中止洪水填埋。
我生成了多个数据集,并与其他公认的解决方案进行了交叉核对,结果似乎产生了正确的结果,但由于此错误,我无法提交。
请帮助我了解其背后的原因。 预先感谢!
#include <iostream>
#include<queue>
#include<stack>
#include<string>
#include<climits>
#include<algorithm>
#include<sstream>
using namespace std;
void convertStringToVector(vector<int>& v,string& data,char delim = ' '){
stringstream ss(data);
string numstr;
while(getline(ss,numstr,delim )){
v.push_back(stoi(numstr));
}
}
typedef struct Node{
int value;
bool visited;
int pos;
Node(int val,int pos,bool isvisited = false){
this->value = val;
this->pos = pos;
this->visited = isvisited;
}
}Node;
typedef struct Tank{
int level;
Tank(int capacity = 0){
this->level = capacity;
}
}Tank;
void fillSpot(int index,int level,vector<Node>& graph,vector<Node>& ograph,Tank& tank,int rmax,int cmax){
int pos = graph[index].pos;
vector<int> rr = {1,-1,0};
vector<int> cc = {0,1,-1};
Node& currentNode = ograph[pos];
int x = int(pos / cmax);
int y = pos % cmax;
int min = INT_MAX;
int currentLevel = currentNode.value;
for(int i = 0; i< rr.size(); i++){
int newx = x + rr[i];
int newy = y + cc[i];
int newpos = (newx * cmax) + newy;
if(newx <0 || newy < 0 || newx >=rmax || newy>=cmax){
return;
}
int neighbour_level = ograph[newpos].value;
if(neighbour_level < level || neighbour_level == currentLevel){
return;
}
if(neighbour_level > level && neighbour_level < min){
min = neighbour_level;
}
}
if(min < INT_MAX && min > currentLevel ){
tank.level = tank.level + (min - currentNode.value);
currentNode.value = min;
}
};
int explore_neighbours(int currNodePos,int cmax,queue<int>& que,int surfaceHeight){
Node& currNode = ograph[currNodePos];
int level = currNode.value;
int pos = currNode.pos;
vector<int> rr = {1,-1};
int x = int(pos / cmax);
int y = pos % cmax;
int min = INT_MAX;
for(int i = 0; i< rr.size(); i++){
int newx = x + rr[i];
int newy = y + cc[i];
int newpos = (newx * cmax) + newy;
if(newx <0 || newy < 0 || newx >=rmax || newy>=cmax){
return -1;
}
Node& neighbourNode = ograph[newpos];
int neighbour_level = ograph[newpos].value;
if(neighbour_level < surfaceHeight){
return -1;
}
if(neighbour_level == level && !neighbourNode.visited){
neighbourNode.visited = true;
que.push(neighbourNode.pos);
}
if(neighbour_level > surfaceHeight && neighbour_level < min && !neighbourNode.visited){
min = neighbour_level;
}
}
return min;
};
void fillSurface(int index,int cmax){
int pos = graph[index].pos;
queue<int> que;
stack<int> stk;
const int LOWER_HEIGHT_FOUND = -1;
int minSurfaceLevel = INT_MAX;
bool abrupt_break = false;
Node& currentNode = ograph[pos];
que.push(currentNode.pos);
int currentLevel = currentNode.value;
while(!que.empty()){
int currNodePos = que.front();
que.pop();
Node& currNode = ograph[currNodePos];
stk.push(currNodePos);
currNode.visited = true;
int newMinSurfaceLevel = explore_neighbours(currNodePos,graph,ograph,tank,rmax,cmax,que,currentLevel);
if(newMinSurfaceLevel == LOWER_HEIGHT_FOUND){
abrupt_break = true;
break;
}
if(newMinSurfaceLevel > currentLevel && newMinSurfaceLevel < minSurfaceLevel){
minSurfaceLevel = newMinSurfaceLevel;
}
}
if(abrupt_break){
while(!que.empty()){
Node & n = ograph[que.front()];
que.pop();
n.visited = false;
}
}
while(!stk.empty()){
int nodePos = stk.top();
stk.pop();
Node& n = ograph[nodePos];
if(abrupt_break){
n.visited = false;
}else if(minSurfaceLevel < INT_MAX){
tank.level = tank.level + (minSurfaceLevel - currentLevel);
n.value = minSurfaceLevel;
}
n.visited = false;
}
}
void buildGraph(){
string testcases;
getline(cin,testcases);
int testcase = 0;
while(testcase < stoi(testcases)){
vector<Node> graph,ograph;
Tank tank = Tank();
string dims;
getline(cin,dims);
vector<int> dimensions;
convertStringToVector(dimensions,dims);
int rmax = dimensions[0];
int cmax = dimensions[1];
for (int i =0 ; i < rmax; i++){
string row;
getline(cin,row);
vector<int> rowdata;
convertStringToVector(rowdata,row,' ');
for(int j= 0; j < cmax; j++){
int pos = i * cmax + j;
int val = rowdata[j];
Node gn = Node(val,pos,false);
Node ogn = Node(val,false);
graph.push_back(gn);
ograph.push_back(ogn);
}
}
//sort the graph based on value
sort(graph.begin(),graph.end(),[](Node const& n1,Node const& n2)->bool{
return n1.value < n2.value;
});
for(int i = 0; i < graph.size(); i++){
Node leastfillednode = graph[i];
int position = leastfillednode.pos;
int level = leastfillednode.value;
fillSpot(i,level,cmax);
fillSurface(i,cmax);
}
cout<<tank.level<<endl;
testcase++;
}
}
int main() {
buildGraph();
return 0;
}
解决方法
vector<Node> graph,ograph;
Tank tank = Tank();
string dims;
getline(cin,dims);
vector<int> dimensions;
convertStringToVector(dimensions,dims);
int rmax = dimensions[0];
int cmax = dimensions[1];
在没有看到输入的情况下,很难知道出了什么问题,但是我看到了一些可以防范的早期机会。
如果在getline(cin,dims);
之后,字符串为空或数字太小怎么办? dimensions
最初是空的,您绝不会验证其大小。当您使用dimensions
的前2个元素时,肯定会遇到麻烦。
我会检查类似的东西,以确保尺寸符合您的期望。如果输入不正确,则抛出std::runtime_error
。
一种快速的方法是使用选中的向量访问权限:
int rmax = dimensions.at(0);
int cmax = dimensions.at(1);
您可能知道,vector::at
针对vector::size
检查其参数,而vector::operator[]
则不检查。
查看其余的代码,我没有注意到对失败或前提条件的断言的一次检查。它隐含地假设一切都按计划进行。 SIGABRT
告诉您假设是不正确的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。