Acwing--1097.池塘计数(Flood Fill)

Flood Fill(泛洪填充)_在?为什么不学习的博客-优快云博客

Flood Fill(泛洪填充):从一个起始节点开始,把附近与其连通的节点提取出或填充成不同颜色,直到封闭区域内的所有节点都被处理过为止。
是从一个区域中提取若干个连通的点与其他相邻区域区分开(或分别染成不同颜色)的经典算法。

可以抽象成一个二维矩阵(图片其实就是像素点矩阵),然后从某个点开始向四周扩展,直到无法再扩展为止。

求连通块问题的算法。

具体实现采用BFS或DFS。

BFS求解:可以求出最短路或者判断两者是否连通,不存在爆栈的风险,但空间相对用的多一些而且代码相对来说繁琐一些。

DFS求解:DFS代码简洁,相对好写一些,但存在爆栈的风险,而且不能求出最短路。

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int>PII;
char g[1010][1010];
int dx[8]={0,0,-1,1,1,1,-1,-1};
int dy[8]={1,-1,0,0,1,-1,1,-1};
int n,m;

void bfs(int x,int y)
{
    queue<PII>q;
    q.p
我有一个nc文件,格式如下: Dimensions: time: 660 bnds: 2 x: 3771 y: 1358 Variables: time: ('time',) float64 time_bnds: ('time', 'bnds') float64 x: ('x',) float64 y: ('y',) float64 spatial_ref: () int32 pre: ('time', 'y', 'x') int16 Variable Data (First 5 Rows): Variable: time [ 0. 31. 59. 90. 120.] Variable: time_bnds [[ 0. 31.] [ 31. 59.] [ 59. 90.] [ 90. 120.] [120. 151.]] Variable: x [90.50672201 90.51505534 90.52338867 90.53172201 90.54005534] Variable: y [35.77295736 35.76462403 35.75629069 35.74795736 35.73962403] Variable: spatial_ref 1 Variable: pre [[[-- -- -- ... -- -- --] [-- -- -- ... -- -- --] [-- -- -- ... -- -- --] ... [-- -- -- ... -- -- --] [-- -- -- ... -- -- --] [-- -- -- ... -- -- --]] [[-- -- -- ... -- -- --] [-- -- -- ... -- -- --] [-- -- -- ... -- -- --] ... [-- -- -- ... -- -- --] [-- -- -- ... -- -- --] [-- -- -- ... -- -- --]] [[-- -- -- ... -- -- --] [-- -- -- ... -- -- --] [-- -- -- ... -- -- --] ... [-- -- -- ... -- -- --] [-- -- -- ... -- -- --] [-- -- -- ... -- -- --]] [[-- -- -- ... -- -- --] [-- -- -- ... -- -- --] [-- -- -- ... -- -- --] ... [-- -- -- ... -- -- --] [-- -- -- ... -- -- --] [-- -- -- ... -- -- --]] [[-- -- -- ... -- -- --] [-- -- -- ... -- -- --] [-- -- -- ... -- -- --] ... [-- -- -- ... -- -- --] [-- -- -- ... -- -- --] [-- -- -- ... -- -- --]]] Grid resolution (approx.): lon ≈ 0.0083°, lat ≈ -0.0083° 我想对降雨数据进行短期旱涝急转指数SDFAI的计算,计算公式如下:(Pj-Pi)*(|Pi|+|Pj|)*3.2^(-|Pi+Pj|),Pi为第i月的标准化降水量(i=5,6,7),j=i+1,SDFAI计算的时间尺度是一个月,我要计算每年5-8月的sdfai指数,即计算5-6 6-7 7-8三个月的指数,用python该如何实现或者用matlab效果会更好?
最新发布
09-11
<think> 根据问题描述,我们需要计算SDFAI指数,公式为:(Pj - Pi) * (|Pi| + |Pj|) * 3.2^(-|Pi+Pj|) 其中Pi和Pj是标准化后的降水量,且时间尺度为一个月。我们需要计算每年5-8月期间相邻两个月的指数,即5-6月、6-7月、7-8月。 数据说明: 我们有一个NetCDF文件,包含以下关键变量: time: 时间,有660个时间点,表示从某年开始的每个月(数据可能是按月记录)。 pre: 降水量数据,维度为(time, y, x),即每个时间点对应一个二维空间网格(y行x列)。 步骤: 1. 读取NetCDF文件,提取降水量数据(pre)和时间变量(time)。 2. 由于我们要计算每年5-8月的数据,因此需要先确定每年5月、6月、7月、8月的数据位置。 假设时间变量是以某种形式(如从1900年1月1日开始的月份偏移)存储的,我们需要将其转换为可识别的年月。 3. 对每个网格点,每年5-8月共四个月,我们要计算相邻两个月的SDFAI(即5-6,6-7,7-8)。 4. 注意:公式中的Pi和Pj是标准化降水量。因此,我们首先需要对降水量进行标准化处理。 标准化方法:通常是对同一月份的所有年份数据求均值和标准差,然后进行去均值和除以标准差。 但是,问题要求计算的是“标准化降水”,通常标准化降水指数(SPI)计算比较复杂,但这里没有具体说明。 根据公式,这里应该是标准化后的值,即均值为0,标准差为1。然而,公式中原始公式可能是针对月降水量的标准化。 然而,问题中并没有给出标准化方法的具体细节,但通常标准化降水指数(SPI)是常用的,计算SPI需要拟合gamma分布然后转换为标准正态分布。但这里可能简化为: Pi = (原始降水量 - 该月多年平均降水量) / 该月多年标准差 注意:标准化是按月进行的,即对于每个网格点,将每年1月的数据一起计算平均值和标准差,然后标准化;同理2月,3月,...,12月。 5. 但是,我们只需要5-8月的数据,所以只需要关注这四个月的数据。 具体步骤: 1) 读取时间,将其转换为年月(例如,假设时间是从某个参考时间开始的月份数,我们可以计算出年份和月份)。 2) 创建数组,用于存储标准化后的5-8月降水(每年每个网格点)。 3) 对每个月(5,6,7,8)分别计算多年该月份的均值和标准差(除年份外的其他年份同月),然后进行标准化。 4) 对于每一年,计算相邻两个月的SDFAI指数(5-6,6-7,7-8)。注意:每年有3个指数值。 5) 将结果保存为新的数组,维度为(年份,3,y, x)—— 即每年有三个指数值(对应三个时间段),每个指数值是一个二维空间场。 6. 由于数据量可能很大(3771x1358网格点),我们需要注意计算效率。可以使用xarray和dask(如果数据太大)来处理,或者使用循环但优化计算。 我们将使用Python的xarray库来处理NetCDF文件,因为它非常适合多维数组操作,并且可以处理大型数据集。 假设: 时间坐标已经转换成了cftime或datetime格式。如果没有,我们需要进行转换。 由于原始数据的时间是float64,并且给出了示例值[0,31,59,...],看起来像是从某个月开始的累计天数?但描述中变量time的维度是(time,),而时间边界则是成对出现。我们需要根据时间边界来理解?但问题中要求的是月份。 但是,从时间边界来看,第一个时间边界是[0,31](31天),第二个[31,59](28天),第三个[59,90](31天),第四个[90,120](30天),第五个[120,151](31天)——这些天数对应1月、2月、3月、4月和5月?注意:0到31可能是1月,31到59是2月(非闰年),以此类推。 因此,我们可以将时间变量视为每个月的中间(或开始)时间?然后根据时间边界我们可以计算出月份。但是,我们只需知道每个时间点对应的实际年月。 假设每个时间点代表一个月,那么660个时间点就是660个月(55年)。因此,我们可以按顺序将每个月分配一个年月。 例如,从某年1月开始(比如1900年1月): 时间点0:1900年1月 时间点1:1900年2月 ... 那么,我们只需要将时间索引转换为年月,然后提取每年的5月(第5个月)、6月(第6个月)、7月(第7个月)、8月(第8个月)。 步骤: 1. 使用xarray打开数据集。 2. 将时间坐标转换为实际的datetime对象(如果尚未转换)。根据示例,原始时间变量是浮点数,单位可能是天,但我们需要确认单位。查看变量time的属性应该有'unit',例如'days since 1900-01-01'。如果没有,我们需要根据上下文推断。 由于问题中没有给出单位,但数据示例显示time的第一个值为0,第二个为31,第三个为59,第四个为90,第五个为120,这很可能是从某起始时间开始的天数,并且每个时间点代表一个月的开始或中间。 但是,在NetCDF文件中,通常会有units属性。我们可以通过读取该属性来转换时间。 如果单位未知,我们可以假设单位是'days since 1900-01-01'(常见情况)并尝试转换。但为了通用性,我们假设已经读取了单位。 具体代码步骤: 1. 读取数据集 2. 将时间转换为datetime格式(如果xarray自动转换了就不用,否则用num2date) 3. 提取每个时间点的年份和月份。 4. 选择5、6、7、8月的数据。 5. 按年份和月份重新组织数据:我们想要一个数组,其维度为(年份,月份,y, x),其中月份为5,6,7,8四个月。 但是,注意:数据可能不是连续的,可能有缺失年份或月份。所以需要确保每年都有5-8月的数据,否则该年不能计算。 6. 标准化处理:对于每个月(例如5月),我们计算所有年份该月降水量的均值和标准差(在时间维度上),然后对每个网格点进行标准化: standardized = (x - mean) / std 注意:如果标准差为0,则会导致除0错误,所以需要将标准差为0的地方设置为NaN(或忽略,但后续计算时要注意)。 7. 对于每一年,计算三个指数: index_5_6 = (P6 - P5) * (np.abs(P5) + np.abs(P6)) * (3.2 ** (-np.abs(P5+P6))) index_6_7 = (P7 - P6) * ... # 同理 index_7_8 = (P8 - P7) * ... # 同理 8. 将计算结果保存为一个新的变量,维度为(年份,3,y, x),其中第二个维度对应三个时间段(5-6,6-7,7-8)。 9. 可以将结果保存为新NetCDF文件。 由于数据量很大,我们尽量使用向量化操作避免循环。 但是,注意:标准化是按月分别进行的,所以我们可以先提取所有5月、6月、7月、8月的数据,然后分别标准化。 假设我们有: pre_5: 一个三维数组(年份,y, x),表示每年5月的降水 pre_6: 每年6月降水 pre_7: 每年7月降水 pre_8: 每年8月降水 然后,对pre_5、pre_6、pre_7、pre_8分别进行标准化(每个网格点上,在年份维度上计算均值和标准差)。 标准化后,就可以用上面的公式计算相邻两个月的指数。 但是,注意:公式中的Pi和Pj是标准化后的值,我们用P5_std, P6_std, P7_std, P8_std表示。 然后计算: year_index = 0,1,2,...(年份索引) sdfai_5_6 = (P6_std - P5_std) * (np.abs(P5_std) + np.abs(P6_std)) * (3.2 ** (-np.abs(P5_std+P6_std))) 同理计算sdfai_6_7、sdfai_7_8。 最后,将这三个指数按年堆叠起来。 我们将使用xarray的DataSet操作来实现,避免显式循环。 代码示例: 假设我们使用xarray: </think> 根据您的需求,我将提供使用 Python 实现短期旱涝急转指数(SDFAI)计算的完整方案。以下是分步解决方案: ### 解决方案思路 1. **数据预处理**:读取 NetCDF 文件,提取降水数据和时间信息 2. **时间维度处理**:将时间转换为年月格式,筛选5-8月数据 3. **标准化降水**:按月计算标准化降水(Z-score) 4. **SDFAI计算**:实现公式 `(Pj-Pi)*(|Pi|+|Pj|)*3.2^(-|Pi+Pj|)` 5. **结果存储**:将计算结果保存为新 NetCDF 文件 ### Python 实现代码(使用 xarray 和 dask 处理大型数据集) ```python import xarray as xr import numpy as np import pandas as pd # 1. 读取NetCDF文件 ds = xr.open_dataset('input.nc', chunks={'time': 100}) # 分块读取处理大数据 # 2. 时间维度处理(假设时间单位是天数) # 转换为datetime格式(需根据实际时间单位调整) time_units = ds.time.attrs.get('units', 'days since 1900-01-01') times = xr.decode_cf(ds).time # 提取年份和月份 year = times.dt.year month = times.dt.month # 选择5-8月数据 summer_months = ds.sel(time=ds.time.dt.month.isin([5, 6, 7, 8])) # 3. 标准化降水(按月计算Z-score) def standardize_by_month(data): """按月计算标准化降水""" # 按月分组计算均值和标准差 monthly_mean = data.groupby('time.month').mean('time', skipna=True) monthly_std = data.groupby('time.month').std('time', skipna=True) # 标准化处理 standardized = (data.groupby('time.month') - monthly_mean) standardized = standardized.groupby('time.month') / np.maximum(monthly_std, 1e-6) # 避免除零 return standardized # 应用标准化 pre_std = standardize_by_month(summer_months['pre']) # 4. SDFAI计算函数 def calculate_sdfai(pi, pj): """计算单个月对的SDFAI指数""" diff = pj - pi abs_sum = np.abs(pi) + np.abs(pj) exponent = -np.abs(pi + pj) return diff * abs_sum * np.power(3.2, exponent) # 5. 计算每年的指数对(5-6,6-7,7-8) def compute_yearly_sdfai(dataset): """计算每年的SDFAI指数""" years = np.unique(dataset.time.dt.year) results = [] for year in years: year_data = dataset.sel(time=dataset.time.dt.year == year) # 提取各月数据 may = year_data.sel(time=year_data.time.dt.month == 5).pre june = year_data.sel(time=year_data.time.dt.month == 6).pre july = year_data.sel(time=year_data.time.dt.month == 7).pre august = year_data.sel(time=year_data.time.dt.month == 8).pre # 计算三个指数对 may_june = calculate_sdfai(may, june) june_july = calculate_sdfai(june, july) july_august = calculate_sdfai(july, august) # 组合为年度数据 year_sdfai = xr.concat([may_june, june_july, july_august], dim=xr.DataArray(['May-Jun', 'Jun-Jul', 'Jul-Aug'], name='period')) results.append(year_sdfai.expand_dims(dim={'year': [year]})) return xr.concat(results, dim='year') # 6. 执行计算并保存结果 sdfai_result = compute_yearly_sdfai(pre_std.to_dataset(name='pre')) # 添加描述性属性 sdfai_result.attrs = { 'long_name': 'Short-term Drought-Flood Abrupt Alternation Index', 'units': 'dimensionless', 'formula': '(Pj-Pi)*(|Pi|+|Pj|)*3.2^(-|Pi+Pj|)', 'calculation_period': 'May to August' } # 保存结果 sdfai_result.to_netcdf('sdfai_results.nc') print("SDFAI计算完成,结果已保存至sdfai_results.nc") ``` ### 关键代码解释 1. **数据分块读取** (`chunks={'time': 100}`) - 使用 dask 分块处理大型数据集(3771x1358 网格) - 避免一次性加载全部数据导致内存溢出 2. **时间处理** - 自动解码 CF 标准时间格式 - 使用 `.dt.month` 提取月份信息 - 筛选5-8月夏季数据 3. **标准化降水** - 按月分组计算均值和标准差 - 公式:`Z = (X - μ) / σ` - 跳过 NaN 值处理缺失数据 4. **SDFAI核心计算** - 向量化实现计算公式 - 逐月对计算:5-6, 6-7, 7-8 - 使用 `np.power` 优化指数计算 5. **结果存储** - 结果维度:[year, period(3), y, x] - 包含完整的元数据属性 - 直接输出为 NetCDF 格式 ### 对比 MATLAB 方案 - **Python优势**: - 免费开源,`xarray` 和 `dask` 库专为地球科学数据设计 - 分布式计算能力更强(特别适合大型网格数据) - Jupyter 环境更适合交互式分析和可视化 - **MATLAB优势**: - 内置 NetCDF 工具更易用 - 对矩阵运算有略微性能优势 - **推荐结论**:首选 Python 方案,尤其当数据量超过内存大小时 ### 注意事项 1. 标准化处理前需检查降水数据中的缺失值(代码已自动跳过 NaN) 2. 计算结果维度为 [年份, 3(时间段), 经度, 纬度] 3. 实际应用中需根据数据的时间单位调整 `decode_cf` 参数 4. 对于特大网格数据,建议集群环境下使用 `dask.distributed`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值