UVA - 221 Urban Elevations

本文介绍了坐标离散化这一算法技巧,通过实例讲解了如何将无限坐标转化为有限坐标,以便进行高效计算。以建筑物可见性问题为例,详细阐述了坐标离散化的应用过程。
/*
  这题的基本思想是坐标离散化,之前看《挑战程序设计竞赛》时,做过类似的题如下:
  
  GCJ 2008 APAC local onsites C Millionaire
  链接:http://blog.youkuaiyun.com/mofushaohua_ln/article/details/77647763
  说明:这题是概率题,虽然不算是坐标离散化,不过思路也是离散化,当时做这题时,因为是第一次接触离散化这个思想,所以理解的过程相当艰难...但是即使到了现在,我仍然觉得这是一道十分值得重做的概率题
  
  坐标离散化技巧(来自挑战)
  blog: http://blog.youkuaiyun.com/mofushaohua_ln/article/details/77795409
  
  说明:这是做的第二道离散化的题,有了前一道的基础和广搜的基础,所以这题理解时并不是很困难,不过用来复习离散化的思路还是不错的~
  
  
  ****本题思路****(详见入门经典P132)
  建筑物的可见性等价于南墙的可见性,可在输入后直接忽略“深度”参数
  
  一个建筑物可能只有部分可见,但我们不可能枚举所有的x,来查看这个建筑在该处是否可见,因为x多穷多
  
  解决方法:离散化,把无穷变为有限
  
  具体方法:所有x坐标(准确说,是每个宽度范围,对应的两个上下限的x坐标),排序去重,任意两相邻的区间具有相同属性。一个区间要么完全可见,要么完全不可见。只需在这个区间里任选一点,就能判断处一个建筑物是否在整个区间内可见。
  
  如何判断一个建筑物是否在某个坐标处可见?
  首先,建筑物坐标中必须包含这个x坐标,其次,建筑物南边不能有另外一个不比它矮的建筑物也包含这个x坐标
*/



#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 105;
int n;
double x[maxn * 2]; //记录每个建筑物的宽度范围的上下限

struct Building
{
	int id;
	double x, y, w, d, h;
	bool operator < (const Building &a) const
	{
		return x < a.x || (x == a.x && y < a.y);
	}
}b[maxn];

istream& operator >> (istream &in, Building &a)
{
	in >> a.x >> a.y >> a.w >> a.d >> a.h;
	return in;
}

bool cover (int i, double mx)
{
	return b[i].x <= mx && b[i].x + b[i].w >= mx;
}

//判断建筑物 i 在 x = mx处是否可见
bool visible (int i, double mx)
{
	if (!cover(i, mx)) return false;
	for (int k = 0; k < n; k++)
	if (b[k].y < b[i].y && b[k].h >= b[i].h && cover(k, mx)) return false;
	return true;
}

int main()
{
	cin.tie(0);
	cin.sync_with_stdio(false);
	
	int kase = 0;
	while (cin >> n && n)
	{
		for (int i = 0; i < n; i++)
		{
			cin >> b[i];
			x[i * 2] = b[i].x; x[i * 2 + 1] = b[i].x + b[i].w;
			b[i].id = i + 1;
		}
		
		sort(b, b + n);
		sort(x, x + 2 * n);
		
		int m = unique(x, x + n * 2) - x; //去重后,得到m个坐标
		
		if (kase++) cout << endl;
		
		cout << "For map #" << kase << ", the visible buildings are numbered as follows:" << endl << b[0].id;
		for (int i = 1; i < n; i++)
		{
			bool vis = false;
			for (int j = 0; j < m - 1; j++)
			{
				if (visible(i, (x[j] + x[j + 1]) / 2) )
				{
					vis = true;
					break;
				} 
			}
			if (vis) cout << " " << b[i].id;
		}
		cout << endl;
	}
	return 0;
}


转载于:https://www.cnblogs.com/mofushaohua/p/7789443.html

model HeatingSystem // 系统参数 parameter Integer nPipes = 2 "供水管+回水管"; parameter Integer nNodes = 3 "泵出口、用户入口、回水出口"; // 管道参数 parameter Real pipe_lengths[nPipes] = {500, 500} "管道长度(m)"; parameter Real pipe_diameters[nPipes] = {0.08, 0.1} "管道直径(m)"; parameter Real pipe_roughness[nPipes] = {4.5e-5, 4.5e-5} "粗糙度(m)"; parameter Real local_loss_coeffs[nPipes] = {0.5, 0.3} "局部损失系数"; // 流体属性 parameter Real fluid_density = 983.2 "密度(kg/m³)"; parameter Real fluid_viscosity = 0.00046 "粘度(Pa·s)"; // 节点参数 parameter Real node_elevations[nNodes] = {45.2, 42.0, 40.5} "节点高度(m)"; // 泵参数 parameter Real pump_head_input = 32 "泵扬程(m)"; // 主要变量 Real flow_rate( start = 0.018, fixed = false, min = 1e-6, nominal = 0.02 ) "系统流量(m³/s)"; Real pressure_losses[nPipes] "管路压降(Pa)"; Real node_pressures[nNodes] "节点压力(Pa)"; // 中间变量 Real Re[nPipes] "雷诺数"; Real f[nPipes] "摩擦系数"; Real v[nPipes] "管道流速(m/s)"; Real area[nPipes] "管道横截面积(m²)"; Real v_safe[nPipes] "安全流速(m/s)"; Real pumpPower "泵功率(W)"; Real lossPower "损失功率(W)"; Real elevationPower "高程功率(W)"; Real balance "能量平衡(W)"; // 常量 constant Real g = Modelica.Constants.g_n "重力加速度"; constant Real pi = Modelica.Constants.pi "圆周率"; constant Real p_atm = 101325 "标准大气压(pa)"; // 系统动态参数 parameter Real timeConstant = 10 "系统时间常数"; parameter Real pipeInertia = 10000 "管道流体惯性(kg/m)"; // 摩擦系数计算函数 function calculateFrictionFactor input Real Re; input Real eps; // 相对粗糙度 output Real f; protected Real Re_safe = max(Re, 1e-3); Real log_arg, A, B; algorithm if Re_safe <= 2300 then f := 64 / Re_safe; else // 数值稳定Churchill公式 log_arg := max((7/Re_safe)^0.9 + 0.27*eps, 1e-10); A := (-2.457 * log(log_arg))^16; B := max((37530/Re_safe)^16, 1e-16); f := 8 * ((8/Re_safe)^12 + 1/max((A+B)^1.5, 1e-10))^(1/12); end if; // 确保摩擦系数在合理范围内 f := min(max(f, 0.001), 0.1); end calculateFrictionFactor; initial equation der(flow_rate) = 0; // 稳态初始化 sum(pressure_losses) = pump_head_input * fluid_density * g - fluid_density * g * (node_elevations[1] - node_elevations[3]); equation /* ===== 核心物理模型 ===== */ /* 节点压力计算 */ node_pressures[1] = pump_head_input * fluid_density * g + 101325 + node_elevations[1] * fluid_density * g; node_pressures[2] = node_pressures[1] - pressure_losses[1]; node_pressures[3] = 101325 + node_elevations[3] * fluid_density * g; /* 预计算管道面积 */ for i in 1:nPipes loop area[i] = pi * (pipe_diameters[i]/2)^2; end for; /* 压力损失计算 */ for i in 1:nPipes loop // 雷诺数 Re[i] = fluid_density * noEvent(smooth(1, if flow_rate > 1e-6 then flow_rate else 1e-6)) * pipe_diameters[i] / max(fluid_viscosity, 1e-10); // 摩擦系数 f[i] = calculateFrictionFactor(Re[i], pipe_roughness[i]/pipe_diameters[i]); // 流速 v[i] = noEvent(smooth(1, if abs(flow_rate) > 1e-6 then flow_rate / area[i] else 0)); // 安全流速 v_safe[i] = noEvent(smooth(1, if abs(v[i]) > 0.01 then abs(v[i]) else 0.01)); // 压力损失 (关键修复:添加平滑过渡) pressure_losses[i] = noEvent(smooth(1, (f[i] * pipe_lengths[i] / pipe_diameters[i] + local_loss_coeffs[i]) * 0.5 * fluid_density * v_safe[i]^2 * sign(flow_rate) )); end for; /* 流体动力学方程 (关键修复:添加平滑过渡) */ pipeInertia * der(flow_rate) = pump_head_input * fluid_density * g - sum(pressure_losses) - fluid_density * g * (node_elevations[1] - node_elevations[3]) + noEvent(if flow_rate < 1e-5 then 1e-3 else 0); /* ===== 监控与验证 ===== */ // 容差验证(1 Pa容差) assert(node_pressures[1] > node_pressures[2] + 1, "供水管压力递减: " + String(node_pressures[1]) + " > " + String(node_pressures[2])); assert(node_pressures[2] > node_pressures[3] + 1, "回水管压力递减: " + String(node_pressures[2]) + " > " + String(node_pressures[3])); assert(flow_rate > 1e-5, "流量为正: " + String(flow_rate)); // 添加能量守恒验证 pumpPower = flow_rate * (node_pressures[1] - p_atm); lossPower = sum(pressure_losses) * abs(flow_rate); elevationPower = fluid_density * g * (node_elevations[1] - node_elevations[3]) * flow_rate; balance = pumpPower - lossPower - elevationPower; assert(abs(balance) < 10, "能量不平衡: " + String(balance) + " W"); end HeatingSystem; 仿真失败,退出码 0xffffffffffffffff 。 C:/Users/lancable/AppData/Local/Temp/OpenModelica/OMEdit/HeatingSystem/HeatingSystem.exe -port=57084 -logFormat=xmltcp -override=startTime=0,stopTime=1,stepSize=0.002,tolerance=1e-06,solver=dassl,outputFormat=mat,variableFilter=.* -r=C:/Users/lancable/AppData/Local/Temp/OpenModelica/OMEdit/HeatingSystem/HeatingSystem_res.mat -w -lv=LOG_STDOUT,LOG_ASSERT,LOG_STATS -inputPath=C:/Users/lancable/AppData/Local/Temp/OpenModelica/OMEdit/HeatingSystem -outputPath=C:/Users/lancable/AppData/Local/Temp/OpenModelica/OMEdit/HeatingSystem The following assertion has been violated during initialization at time 0.000000 ((abs(balance) < 10.0)) --> "能量不平衡: 1994.99 W" simulation terminated by an assertion at initialization
09-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值