请教水潭积水算法

zsk789889 2009-07-27 11:31:25
问题描述:有一块M*N的四联通的地,每一块的高度手动输入,经过大雨以后,计算这块地的积水量
...全文
213 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
adfas 2009-07-31
  • 打赏
  • 举报
回复
http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1126
zsk789889 2009-07-29
  • 打赏
  • 举报
回复
谢谢
knate 2009-07-29
  • 打赏
  • 举报
回复
你那个没有细看,可能的结果应该是没有对符合条件附近的点继续进行判断.
即没有进行更进一步的搜索.


//我这个是用方法一的伪代码
enum State{Unknown,Border,Record};
//状态记录:未知,边界(刚接触到水),已记录最高水深

class CPoint{
public:
double dLocationX,dLocationY;//该点坐标,事实上可以用vInt的相对位置进行记录,只是相对麻烦点
double dHigh; //地表高度
State eState; //当前是否记录 等状态
double dMax_Depth; //该点存水最大深度
CPoint(double x,double y,double dhigh,double dDepth = 0,State cState=Unknown):
dLocationX(x),dLocationY(y),dHigh(dhigh),dMax_Depth(dDepth),eState(cState){
}; //默认为该点 CPoint 为未知
};


bool No_Invalid(double x,double y,vector<vector<CPoint> >& vInt){
//如果点 (x,y) 仍然在vInt 区域内,即为有效
//返回 true 否则返回false;
}

int main(){
vector<vector<CPoint> > vInt;
vector<double> vScale;
//初始化输入数据:略
// 具体为 vInt为区域 M*N 区域点初始化
// vScale 为区域内各种可能的高度(不重复)//////给所有区域高度排序一下,删除重复高度即可
//输入数据后必须是得到一个矩形区域(所有点为未知). 否则后面处理将出错.(后面程序均没对区域 vInt进行是否有效进行判断)

if(vInt.size()< 3 || vInt.begin()->size() < 3){
cout<<"没有积水"<<endl;
return 0;
}

vector<CPoint> vBorder;
for(vector<CPoint>::iterator p = vInt.begin()->begin();p != vInt.begin()->end();++p){
vBorder.push_back(*p);
p->eState = Border;
}
for(vector<CPoint>::iterator p = vInt.end()->begin();p != vInt.end()->end();++p){
vBorder.push_back(*p);
p->eState = Border;
}
for(vector<vector<CPoint> >::iterator p = vInt.begin()+1;p != vInt.end()-1;++p){
vBorder.push_back(* p->begin());
p->begin()->eState = Border;
vBorder.push_back(*(p->end()-1));
(p->end()-1)->eState = Border;
}
//以上为记录M*N边界的的CPoint 为边界(刚接触到水)



for(vector<double>::iterator pDepth = vScale.begin();pDepth != vScale.end();++ pDepth){
for(vector<CPoint>::iterator p = vBorder.begin();p != vBorder.end();++p){
//如果 *p (坐标为 (p->x,p->y)相邻的四个相邻区域 CPoint Ki(坐标为 (x-1,y),(x+1,y),(x,y-1),(x,y+1) 是否有效 调
// 用No_Invalid(p->x,p->y,vInt)进行判断
//为未知 (Ki.eState ==Unknown)且 && 地表不高于现在的水位深度 (Ki.dHigh <= *pDpeth)
//该CPoint Ki 放入 vBorder vBorder.push_back(Ki);
//改该点状态为Border,并记录此时水位为该点的最大水深 Ki.eState= Border; Ki.dMax_Depth= *pDepth; //Ki为vInt的对应单元
}
for(vector<CPoint>::iterator p = vBorder.begin();p != vBorder.end();++p){
//如果*p 相邻四个区域 没有未知的,从vBorder删除*p (vBorder.delete(*p))
} //删除不可能增加边界的CPoint (Border) 的 CPoint ,减少下一次更高水位历遍的数量

} //实际上是使用图历遍所有该水位能到达的区域

//至此为各个CPoint 能存的最大水深均存在了vInt
//进行统计一下即可



cout<<endl;
return 0;
}
knate 2009-07-28
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 zsk789889 的回复:]
引用 10 楼 knate 的回复:
两种方式:
1方式:是慢慢提升外面的水位,看看水位h什么时候能漫过地表,并记录此时的水位高度.并历遍所有能够购到达的地表(搜索方式),并一一记录
2方式:从地表上慢慢提升水位h,使所有区域地表高度或积水表面均不低于h,看看水什么时候漫出至边界,记录各地表当时的水位.
复杂度均为 M*N*(M+N)



您好,我想知道您这里说的边界是指最外面的边界?

[/Quote]
是的.
M*N区域的边界

可以想象该区域是一个孤岛,水位慢慢上涨,刚能通过海浪(比水位高dx)就能到达时就是该区域能积水的高度
方式2:地下水慢慢涨起来,漫出是就是该区域的积水高度.
编程需要做的就是对不同水位时进行记录.
hhwei1985 2009-07-28
  • 打赏
  • 举报
回复
up
eagerle01 2009-07-28
  • 打赏
  • 举报
回复
没看懂题目的用意
zsk789889 2009-07-28
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 knate 的回复:]
两种方式:
1方式:是慢慢提升外面的水位,看看水位h什么时候能漫过地表,并记录此时的水位高度.并历遍所有能够购到达的地表(搜索方式),并一一记录
2方式:从地表上慢慢提升水位h,使所有区域地表高度或积水表面均不低于h,看看水什么时候漫出置边界,记录各地表当时的水位.
复杂度均为 M*N*(M+N)
[/Quote]


您好,我想知道您这里说的边界是指最外面的边界?
zsk789889 2009-07-28
  • 打赏
  • 举报
回复
您能再说具体点么?
zsk789889 2009-07-28
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 knate 的回复:]
引用 13 楼 zsk789889 的回复:
引用 10 楼 knate 的回复:
两种方式:
1方式:是慢慢提升外面的水位,看看水位h什么时候能漫过地表,并记录此时的水位高度.并历遍所有能够购到达的地表(搜索方式),并一一记录
2方式:从地表上慢慢提升水位h,使所有区域地表高度或积水表面均不低于h,看看水什么时候漫出至边界,记录各地表当时的水位.
复杂度均为 M*N*(M+N)


您好,我想知道您这里说的边界是指最外面的边界?


是的.
M*N区域的边界

可以想象该区域是一个孤岛,水位慢慢上涨,刚能通过海浪(比水位高dx)就能到达时就是该区域能积水的高度
方式2:地下水慢慢涨起来,漫出是就是该区域的积水高度.
编程需要做的就是对不同水位时进行记录.
[/Quote]
谢谢您 如果您有时间希望您能看看我写得 结果有点出不正确
#include "Node.h"
#include "iostream.h"



Node::Node()
{
high = 0;
right = 0;
left = 0;
down = 0;
up = 0;
bulk = 0;

}

Node::~Node()
{

}


int main()
{
int a[20][20];
int i = 0;
int j = 0;
int M = 0;
int N = 0;
int bulk = 0;
int temp = 5;
int count = 0;
int b[20][20];

cout<<"please input M and N!";
cin>>M>>N;
Node node[20][20];






cout<<"请输入每个方块的高度";
for (i=1;i<=M;i++)
for(j=1;j<=N;j++)
cin>>node[i][j].high;
a[i][j] = 1;

for (i=1;i<=M;i++)
for(j=1;j<=N;j++)
{
node[i][j].right = node[i+1][j].high;
node[i][j].left = node[i-1][j].high;
node[i][j].up= node[i][j-1].high;
node[i][j].down = node[i][j-1].high;
}
//-------------------------------计算基本的积水量
//
//--------------------------------打印这个地形
cout<<"地形状况是";
for(j=1;j<=N;j++)
{
cout<<endl;
for (i=1;i<=M;i++)

cout<<node[i][j].high;
}

for (i=1;i<=M;i++)
for(j=1;j<=N;j++)
{
if(node[i][j].high<0)
{
bulk -=node[i][j].high;
node[i][j].high -= node[i][j].high;
}
}
cout<<endl<<"基本的积水量是"<<bulk<<endl;

for (i=1;i<=M;i++)
for(j=1;j<=N;j++)
{
node[i][j].right = node[i+1][j].high;
node[i][j].left = node[i-1][j].high;
node[i][j].up= node[i][j-1].high;
node[i][j].down = node[i][j-1].high;
}
cout<<"计算基本积水后地形状况:"<<endl;
for(j=1;j<=N;j++)
{
cout<<endl;
for (i=1;i<=M;i++)

cout<<node[i][j].high;
}
cout<<endl;
//-------------------------------------------------初始化最外侧的积水高度
for(j=1;j<=N;j++)
{
a[1][j] = node[1][j].high;
a[M][j] = node[M][j].high;
}
for(i=1;i<=M;i++)
{
a[i][1] = node[i][1].high;
a[i][N] = node[i][N].high;
}
i=1;
j=1;

while(i<=M/2||j<N/2)
{
temp = 10;
//------------------------------------寻找一圈里的“孔”
for(int k=j;k<N-j+1;k++)
{
if(a[i][k]<temp)
temp = a[i][k];
}
for( k=j;k<N-j+1;k++)
{
if(a[M-i+1][k]<temp)
temp = a[M-i+1][k];
}
for(int l=i;l<M-i+1;l++)
{
if(a[l][j]<temp)
temp = a[l][j];
}

for( l=i;l<M-i+1;l++)
{
if(a[l][N-j+1]<temp)
temp = a[l][N-j+1];
}
cout<<"第"<<i<<"圈的最低积水高度是"<<temp<<endl;
//----------------------------------------------------
//以下是设置相邻内圈的的积水高度
//----------------------------------------------------------------
for( k=j;k<=N-j+1;k++)
{
if(node[i][k].right <= temp)
a[i+1][k] = temp;
else
a[i+1][k] = node[i][k].right;
}
for(k=j;k<=N-j+1;k++)
{
if(node[M-i+1][k].left <= temp)
a[M-i][k] = temp;
else
a[M-i][k] = node[M-i+1][k].left;
}
for( l=i+1;l<=M-i;l++)
{
if(node[l][j].down <= temp)
a[l][j+1] = temp;
else
a[l][j+1] = node[l][j].down;
}
for( l=i+1;l<=M-i;l++)
{
if(node[l][N-j+1].up <= temp)
a[l][N-j] = temp;
else
a[l][N-j] = node[l][N-j+1].up;
}
i++;
j++;
}



for(j=1;j<=N;j++)
{
cout<<endl;
for (i=1;i<=M;i++)
cout<<a
[i][j];
}
cout<<endl;


for (i=1;i<=M;i++)
for(j=1;j<=N;j++)


{

b[i][j] = a[i][j] - node[i][j].high;
bulk += b[i][j];

}

cout<<endl<<"积水总量是"<<bulk;

return 0;
}
marrco2005 2009-07-27
  • 打赏
  • 举报
回复
四联通的具体含义是什么
knate 2009-07-27
  • 打赏
  • 举报
回复
如果没有记错的话应该是 算法艺术上的一个例题.
knate 2009-07-27
  • 打赏
  • 举报
回复
两种方式:
1方式:是慢慢提升外面的水位,看看水位h什么时候能漫过地表,并记录此时的水位高度.并历遍所有能够购到达的地表(搜索方式),并一一记录
2方式:从地表上慢慢提升水位h,使所有区域地表高度或积水表面均不低于h,看看水什么时候漫出置边界,记录各地表当时的水位.
复杂度均为 M*N*(M+N)
matrixcl 2009-07-27
  • 打赏
  • 举报
回复
看成积水潭算法了
zsk789889 2009-07-27
  • 打赏
  • 举报
回复
是 这样
UU_Yang 2009-07-27
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 zsk789889 的回复:]
每一块单位是一平方米,比如四周都是两米 那么积水量就是两立方米
[/Quote]

是不是说,某地四周都是两米,此地就成为一个积水潭,能存水?
而如果四周都低于某地,那么此地就不存水?
zsk789889 2009-07-27
  • 打赏
  • 举报
回复
就是一块地是四连通的 有M*N块每块一平方米,高度手动设定,经过一场雨,问土地的积水量
Rock_And_Roll 2009-07-27
  • 打赏
  • 举报
回复
没有看懂,说具体一点。
zsk789889 2009-07-27
  • 打赏
  • 举报
回复
每一块单位是一平方米,比如四周都是两米 那么积水量就是两立方米
UU_Yang 2009-07-27
  • 打赏
  • 举报
回复
有点不明白,积水量是个什么概念,和地的高低有什么关系呢?
如果一块高地和另一块低地相邻,他们的积水量又是什么关系?
zsk789889 2009-07-27
  • 打赏
  • 举报
回复
不好意思 是四连通,就是只与上 下 左 右 有关系的,和左上 左下 右上 右下 是没有关系的,就是说从一块出发经过向上向下向左向右就能走过全图。

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧