Lakes in Berland(CF #375 Div. 2)

本文解析了CodeForces D题的解决方案,采用DFS搜索算法找出所有湖泊,并通过贪心策略选择填充部分湖泊以达到题目要求。文章提供了完整的AC代码及实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

练习题这道题,这是一道思路很明确的题(dfs裸题+简单贪心),不过在实现细节上有些要注意的地方。

题目大意:在一个n×m的地方上有陆地和湖,那些和边缘连接的水域视为海,题目给出最后要保留k个湖,由你计算出最少要填多少陆地,并把图画出来。附链接:http://codeforces.com/problemset/problem/723/D

大体思路:计算出有num个湖,并记录下最开始找到这个湖的位置和湖的面积,保存在一个数组Node[3000]里,然后对Node数组排序,取出num-k个湖填满,计算要填的总面积,最后输出。思路很清晰。不过在判断是否是湖这一点上需要想一想怎么写。

以下是ac代码

#include<stdio.h>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

struct node{
    int x,y;
    int cnt;
}Node[3000];

const int maxn=60;
int n,m;
char box[maxn][maxn];
int vis[maxn][maxn];
int ans,flag;
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
int cmp(node a,node b){
    return a.cnt<b.cnt;
}
void dfs(int bx,int by){  //判断有多少个湖的函数
    if(bx<=0||bx>=n-1||by<=0||by>=m-1){   
        flag=1;
        return;
    }
    vis[bx][by]=1;
    ans++;
    for(int i=0;i<4;i++){
        int x=bx+dx[i];
        int y=by+dy[i];
        if(box[x][y]=='.'&&!vis[x][y])
            bfs(x,y);
    }
}
void rdfs(int bx,int by){  //填湖的函数
    if(bx<0||bx>=n||by<0||by>=m)
        return;
    box[bx][by]='*';
    for(int i=0;i<4;i++){
        int x=bx+dx[i];
        int y=by+dy[i];
        if(box[x][y]=='.')
            rbfs(x,y);
    }
}
int main(){
    int k;
    while(scanf("%d%d%d",&n,&m,&k)!=EOF){
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++)
            scanf("%s",box[i]);
        int num=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++){
                if(box[i][j]=='.'&&!vis[i][j]){
                    ans=0;
                    flag=0;  //判断标志
                    dfs(i,j);
                    if(!flag)
                        Node[num++]={i,j,ans};
                }
            }
        /*
        for(int i=0;i<num;i++)
            printf("%d %d %d\n",Node[i].x,Node[i].y,Node[i].cnt);
        */
        sort(Node,Node+num,cmp);
        int sum=0;
        for(int i=0;i<num-k;i++){
            rdfs(Node[i].x,Node[i].y);  //填湖
            sum+=Node[i].cnt;
        }
        printf("%d\n",sum);
        for(int i=0;i<n;i++)
            printf("%s\n",box[i]);
    }
    return 0;
}


import numpy as np import matplotlib.pyplot as plt from netCDF4 import Dataset import cartopy.crs as ccrs import cartopy.feature as cfeature from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER from scipy.ndimage import gaussian_filter # 地形平滑(可选) def plot_simple_contour(wrfout_file, target_lon, target_lat, radius_km=55, contour_interval=20, smooth_terrain=True): # 1. 读取WRF数据 nc = Dataset(wrfout_file, &#39;r&#39;) try: lats = nc.variables[&#39;XLAT&#39;][:] lons = nc.variables[&#39;XLONG&#39;][:] hgt = nc.variables[&#39;HGT&#39;][:] # 处理时间维度(取第一时次) if len(lats.shape) == 3: lats = lats[0, :, :] lons = lons[0, :, :] hgt = hgt[0, :, :] # 2. 智能截取目标网格(按公里数动态计算范围) deg2km = 111 # 1度≈111公里 n = max(10, int(radius_km / deg2km * max(lats.shape))) # 保证至少10个网格 # 找目标点在网格中的索引 lat_diff = np.abs(lats - target_lat) lon_diff = np.abs(lons - target_lon) min_idx = np.argmin(lat_diff + lon_diff) sy, sx = np.unravel_index(min_idx, lats.shape) # 边界保护(防止索引越界) sy_min = max(0, sy - n) sy_max = min(lats.shape[0] - 1, sy + n) sx_min = max(0, sx - n) sx_max = min(lats.shape[1] - 1, sx + n) # 截取目标区域 target_lats = lats[sy_min:sy_max, sx_min:sx_max] target_lons = lons[sy_min:sy_max, sx_min:sx_max] target_hgt = hgt[sy_min:sy_max, sx_min:sx_max] # 数据校验 if target_hgt.size == 0: raise ValueError("目标区域无数据!请检查经纬度或半径设置") # 3. 地形平滑(可选) if smooth_terrain: target_hgt = gaussian_filter(target_hgt, sigma=1.2) # 轻度平滑 # 4. 创建地图投影和绘图 # 使用PlateCarree投影(经纬度投影) projection = ccrs.PlateCarree() # 创建图形和轴 fig = plt.figure(figsize=(10, 8), dpi=150) ax = plt.subplot(111, projection=projection) # 5. 添加地图底图 # 添加陆地、海洋、湖泊和海岸线特征 ax.add_feature(cfeature.LAND, facecolor=&#39;#f5f5dc&#39;, edgecolor=&#39;none&#39;) # 浅米色陆地 ax.add_feature(cfeature.OCEAN, facecolor=&#39;#e6f2ff&#39;, edgecolor=&#39;none&#39;) # 浅蓝色海洋 ax.add_feature(cfeature.LAKES, facecolor=&#39;#e6f2ff&#39;, edgecolor=&#39;none&#39;) # 湖泊 ax.add_feature(cfeature.COASTLINE, edgecolor=&#39;#666666&#39;, linewidth=0.8) # 海岸线 ax.add_feature(cfeature.BORDERS, linestyle=&#39;:&#39;, edgecolor=&#39;#999999&#39;, linewidth=0.8) # 国界线 # 6. 设置地图范围 # 计算目标区域的边界 lon_min, lon_max = target_lons.min(), target_lons.max() lat_min, lat_max = target_lats.min(), target_lats.max() # 扩展10%的范围以获得更好的上下文 lon_center = (lon_min + lon_max) / 2 lat_center = (lat_min + lat_max) / 2 lon_extent = (lon_max - lon_min) * 0.1 lat_extent = (lat_max - lat_min) * 0.1 # 设置地图范围 ax.set_extent([ lon_min - lon_extent, lon_max + lon_extent, lat_min - lat_extent, lat_max + lat_extent ], crs=projection) # 7. 添加网格线和标签 gl = ax.gridlines(crs=projection, draw_labels=True, linewidth=0.5, color=&#39;gray&#39;, alpha=0.5, linestyle=&#39;--&#39;) gl.top_labels = False gl.right_labels = False gl.xformatter = LONGITUDE_FORMATTER gl.yformatter = LATITUDE_FORMATTER gl.xlabel_style = {&#39;size&#39;: 9, &#39;color&#39;: &#39;black&#39;} gl.ylabel_style = {&#39;size&#39;: 9, &#39;color&#39;: &#39;black&#39;} # 8. 绘制等高线(在地图底图上) # 计算合理等高线范围(用百分位数避免极端值) hgt_min = np.percentile(target_hgt, 5) hgt_max = np.percentile(target_hgt, 95) levels = np.arange(hgt_min, hgt_max + contour_interval, contour_interval) # 等高线(深棕色线条) contour = ax.contour( target_lons, target_lats, target_hgt, levels=levels, colors=&#39;#8B4513&#39;, # 深棕色 linewidths=1.5, transform=projection, zorder=2 ) # 9. 等高线标注(深棕色) ax.clabel( contour, contour.levels, # 标注所有层级 inline=True, fontsize=9, fmt="%d", colors=&#39;#8B4513&#39;, # 深棕色 zorder=3 ) # 10. 目标点标注(红色星形) ax.plot( target_lon, target_lat, &#39;r*&#39;, markersize=12, transform=projection, zorder=4, label=f&#39;目标点 ({target_lon:.2f}°E, {target_lat:.2f}°N)&#39; ) ax.legend( loc=&#39;upper right&#39;, fontsize=10, frameon=True, framealpha=0.8, edgecolor=&#39;gray&#39; ) # 在右上角添加指北针 compass_x = lon_max - 0.1 * (lon_max - lon_min) compass_y = lat_max - 0.1 * (lat_max - lat_min) ax.text(compass_x, compass_y, &#39;N&#39;, ha=&#39;center&#39;, va=&#39;center&#39;, fontsize=12, fontweight=&#39;bold&#39;, transform=projection, zorder=5) ax.plot([compass_x, compass_x], [compass_y, compass_y + 0.2], color=&#39;black&#39;, linewidth=1, transform=projection, zorder=5) # 13. 调整布局并显示 plt.tight_layout() plt.subplots_adjust(top=0.92) # 为标题留出空间 plt.show() finally: nc.close() # ------------------- 调用示例 ------------------- if __name__ == "__main__": wrfout_file = r"C:\1\wrfout_d03_2024-01-21_18" # 替换为实际路径 target_lon = 92.070 # 目标经度 target_lat = 31.455 # 目标纬度 plot_simple_contour( wrfout_file, target_lon, target_lat, radius_km=25, # 范围大小 contour_interval=20, # 等高线间隔(可调整) smooth_terrain=True # 平滑地形(让线条更自然) ) 修改代码,经纬度统一保留三位小数
最新发布
07-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值