F. Equalize the Array (map、思维)

本文介绍了一种算法,通过实例演示如何在给定数值分布中删除最少元素,使剩余数量尽可能相同。通过逐步调整目标数量,展示了如何计算每一步的最优操作并更新结果。核心代码展示了如何使用C++实现这一过程,最终目标是找到在不同数量级下删除最少数量的解决方案。

题目

思路:
看一个例子
x:y 表示 拥有x个相同的数有y个(2:3 1 1 2 2 3 3)

现在有 4:5 3:3 1:8 即 有5个数量为4的数 3个数量为3的数 8个数量为1的数

现在我们要求使得剩下的数的数量都相同的最少删去数的个数,即让剩下数的个数最大

我们假设要让最后所有的数都剩下数量为4,那么把1和3的所有数删掉即可,剩下数的个数4*5=20.

继续这个过程如要让剩下的数数量都为3,那么我们需将那5个数量为4的数各自删掉一个数,再加上所有数量为3的数,即为20-(4-3)*5+3 * 3=24,此时有3+5个数量为3的数

再继续,让剩下的数的个数都为1,需将8个数量为3的数都相减2再加上8个数量为1的数 24-(3-1)*8+1 *8=16.
最终答案取20 24 16 所有情况的最大值24

Code:

#include<iostream>
#include<map>
using namespace std;
typedef long long ll;
const int Max = 1e6 + 5;
int Mod = 1e9 + 7;
ll lst[Max];

int main()
{
	int t;cin >> t;
	while (t--)
	{
		map<ll, ll,greater<ll>> ma1, ma2;
		int n;cin >> n;
		for (int i = 1;i <= n;i++) { cin >> lst[i];ma1[lst[i]]++; }
		for (auto i = ma1.begin();i != ma1.end();i++)ma2[i->second]++;
		ll sum = ma2.begin()->first * ma2.begin()->second;
		ll ma = sum;auto j = ma2.begin();
		for (auto i = ++ma2.begin();i != ma2.end();i++)
		{
			sum += i->first * i->second;
			sum -= (j->first - i->first) * j->second;
			i->second += j->second;
			ma = max(ma, sum);
			j = i;
		}
		cout << n - ma << endl;
	}
}
代码是import os import json import glob import random import numpy as np from skimage.feature import hog from skimage import exposure from sklearn.model_selection import train_test_split from sklearn.svm import SVC from sklearn.ensemble import RandomForestClassifier from sklearn.neighbors import KNeighborsClassifier from sklearn.linear_model import LogisticRegression from sklearn.metrics import classification_report, confusion_matrix import torch from torchvision import transforms from PIL import Image import timm import matplotlib.pyplot as plt import seaborn as sns from skimage.io import imread # ===================== # 读取样本 # ===================== LABEL_MAP = { "corona": 0, "NonPD": 1, "surface": 2, "internal": 3 } def load_samples_from_dir(root_dir: str): samples = [] image_paths = glob.glob(os.path.join(root_dir, "*.jpg")) for img_path in image_paths: base = os.path.splitext(img_path)[0] json_path = base + ".json" if not os.path.exists(json_path): print(f"[WARN] JSON not found for image: {img_path}") continue with open(json_path, "r", encoding="utf-8") as f: data = json.load(f) flags = data.get("flags", {}) label_name = None for k in LABEL_MAP.keys(): if flags.get(k, False): label_name = k break if label_name is None: print(f"[WARN] No valid label in JSON: {json_path}") continue label_idx = LABEL_MAP[label_name] samples.append((img_path, label_idx)) return samples # ===================== # HOG 特征提取 # ===================== def extract_hog_features(img_path): image = imread(img_path) # 将图像转换为灰度图 image = np.dot(image[...,:3], [0.2989, 0.5870, 0.1140]) # RGB to grayscale fd, hog_image = hog(image, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(2, 2), visualize=True, multichannel=False) # 你可以进一步增强HOG图像(可选) hog_image_rescaled = exposure.rescale_intensity(hog_image, in_range=(0, 10)) return fd # 返回HOG特征向量 # ===================== # 对比模型:SVM / 随机森林 / kNN / 逻辑回归 # ===================== def train_and_evaluate(X_train, y_train, X_test, y_test, model_type="SVM"): if model_type == "SVM": model = SVC(kernel="linear", random_state=42) elif model_type == "RandomForest": model = RandomForestClassifier(n_estimators=100, random_state=42) elif model_type == "kNN": model = KNeighborsClassifier(n_neighbors=5) elif model_type == "LogisticRegression": model = LogisticRegression(max_iter=1000, multi_class="multinomial", solver="lbfgs") # 训练模型 model.fit(X_train, y_train) # 在测试集上评估 y_pred = model.predict(X_test) # 输出分类指标 print(f"Model: {model_type}") print(f"Accuracy: {np.mean(y_pred == y_test):.4f}") print("Classification Report:") print(classification_report(y_test, y_pred, target_names=[label for label in LABEL_MAP.keys()])) print("Confusion Matrix:") print(confusion_matrix(y_test, y_pred)) return model # ===================== # 训练和测试 # ===================== def main(): data_root = "split" # 修改为你的数据路径 train_dir = os.path.join(data_root, "train") test_dir = os.path.join(data_root, "test") # 加载训练集和测试集 train_samples = load_samples_from_dir(train_dir) test_samples = load_samples_from_dir(test_dir) # 提取 HOG 特征和标签 X_train = [] y_train = [] for img_path, label in train_samples: features = extract_hog_features(img_path) X_train.append(features) y_train.append(label) X_test = [] y_test = [] for img_path, label in test_samples: features = extract_hog_features(img_path) X_test.append(features) y_test.append(label) # 转换为 numpy 数组 X_train = np.array(X_train) y_train = np.array(y_train) X_test = np.array(X_test) y_test = np.array(y_test) # 对比模型训练和评估 models = ["SVM", "RandomForest", "kNN", "LogisticRegression"] for model_type in models: print(f"================== {model_type} ==================") model = train_and_evaluate(X_train, y_train, X_test, y_test, model_type=model_type) if __name__ == "__main__": main() def plot_confusion_matrix(y_true, y_pred, class_names, save_path="confusion_matrix.png"): cm = confusion_matrix(y_true, y_pred) plt.figure(figsize=(8, 6)) sns.heatmap(cm, annot=True, fmt='g', cmap='Blues', xticklabels=class_names, yticklabels=class_names) plt.title("Confusion Matrix") plt.ylabel("True label") plt.xlabel("Predicted label") plt.tight_layout() plt.savefig(save_path) plt.show()
12-08
修改下面的代码,使得模型计算速度加大,其中内容可以更换使用更高级更快速的函数模块等,例如图像分割、砾石体积计算排序等。使得ct图像处理的更完美、质量更高,砾石提取的更快速。代码如下:import os import re import time import warnings import numpy as np import cupy as cp import cupyx.scipy.ndimage as cpx_ndi import tifffile as tiff from skimage import filters, morphology, measure, segmentation, feature, exposure from scipy import ndimage as ndi from sklearn.decomposition import PCA from concurrent.futures import ProcessPoolExecutor import matplotlib.pyplot as plt import logging import trimesh from tqdm import tqdm, trange # 设置路径和参数 input_path = r"E:\GHJ\shaliyan\XY" output_dir = r"E:\GHJ\shaliyan\keli" voxel_size = 38.6598 # 微米 target_count = 1500 # 提取的最大颗粒数量 def natural_sort_key(s): """自然排序键函数,用于正确排序文件名""" return [int(text) if text.isdigit() else text.lower() for text in re.split(r'(\d+)', s)] def read_tiff_sequence(folder_path): """从文件夹读取TIFF序列,使用GPU加速""" print("读取TIFF序列...") tiff_files = [f for f in os.listdir(folder_path) if f.endswith(('.tif', '.tiff'))] tiff_files.sort(key=natural_sort_key) first_image = tiff.imread(os.path.join(folder_path, tiff_files[0])) height, width = first_image.shape volume_gpu = cp.zeros((len(tiff_files), height, width), dtype=cp.float32) # 添加进度条 batch_size = 50 with tqdm(total=len(tiff_files), desc="读取图像") as pbar: for i in range(0, len(tiff_files), batch_size): batch_files = tiff_files[i:i+batch_size] for j, filename in enumerate(batch_files): img_path = os.path.join(folder_path, filename) volume_gpu[i+j] = cp.asarray(tiff.imread(img_path).astype(np.float32)) pbar.update(len(batch_files)) return volume_gpu def preprocess_ct_gpu(volume_gpu): """在GPU上预处理CT体积数据""" print("预处理CT数据 (GPU加速)...") # 中值滤波去噪 print("应用中值滤波...") filtered_volume = cpx_ndi.median_filter(volume_gpu, size=3) # 对比度增强 print("应用对比度增强...") enhanced_volume = cp.zeros_like(filtered_volume) for i in tqdm(range(filtered_volume.shape[0]), desc="增强对比度"): slice_data = filtered_volume[i] slice_min = cp.min(slice_data) slice_max = cp.max(slice_data) normalized = (slice_data - slice_min) / (slice_max - slice_min) * 255 hist = cp.histogram(normalized.flatten(), bins=256, range=(0, 256))[0] cdf = cp.cumsum(hist) cdf_normalized = 255 * cdf / cdf[-1] enhanced_volume[i] = cp.interp(normalized.flatten(), cp.arange(256), cdf_normalized).reshape(normalized.shape) # Otsu阈值分割 print("应用阈值分割...") middle_slice = cp.asnumpy(enhanced_volume[enhanced_volume.shape[0]//2]) thresh = filters.threshold_otsu(middle_slice) binary_volume = enhanced_volume > thresh return binary_volume def segment_grains_gpu(binary_volume_gpu, min_distance=3, footprint_size=3): """使用GPU加速的分水岭算法分割砾石""" print("分割砾石 (GPU加速)...") # 转到CPU进行距离变换(因为GPU版本可能不稳定) binary_cpu = cp.asnumpy(binary_volume_gpu) # 距离变换 print("计算距离变换...") distance = ndi.distance_transform_edt(binary_cpu) distance_gpu = cp.asarray(distance) # 使用maximum_filter找局部极大值 print("寻找局部极大值...") size = footprint_size if footprint_size % 2 == 1 else footprint_size + 1 max_filtered = cpx_ndi.maximum_filter(distance_gpu, size=size) # 局部极大值检测 local_max = (distance_gpu == max_filtered) & (distance_gpu > min_distance) local_max = cp.asnumpy(local_max & binary_volume_gpu) # 去除小连通域 local_max = morphology.remove_small_objects(local_max, min_size=2) # 标记种子点 markers = measure.label(local_max) # 分水岭分割 print("应用分水岭算法...") labels = segmentation.watershed(-distance, markers, mask=binary_cpu) return labels def calculate_volumes(labels): """计算每个标签的体积""" print("计算颗粒体积...") unique_labels = np.unique(labels) unique_labels = unique_labels[unique_labels > 0] # 排除背景标签0 volumes = {} for label in tqdm(unique_labels, desc="计算体积"): volumes[label] = np.sum(labels == label) return volumes def extract_and_save_grains_high_quality(labels, output_dir, voxel_size, target_count): """提取每个砾石并保存为高质量STL文件""" print("提取并保存高质量STL文件...") os.makedirs(output_dir, exist_ok=True) # 计算体积并排序 volumes = calculate_volumes(labels) sorted_labels = sorted(volumes.keys(), key=lambda x: volumes[x], reverse=True) if len(sorted_labels) > target_count: sorted_labels = sorted_labels[:target_count] print(f"将提取 {len(sorted_labels)} 个最大的颗粒") # 使用进度条显示多进程处理进度 with ProcessPoolExecutor(max_workers=os.cpu_count()) as executor: futures = [] for i, label in enumerate(sorted_labels): futures.append(executor.submit( process_single_grain, labels, label, i, output_dir, voxel_size, volumes[label] )) # 使用tqdm显示进度 for _ in tqdm(futures, desc="处理颗粒", total=len(futures)): _.result() def process_single_grain(labels, label, index, output_dir, voxel_size, volume): """处理单个颗粒并生成高质量STL""" try: print(f"处理颗粒 {index+1} (标签 {label}, 体积 {volume} 体素)") # 提取当前砾石的二值掩模 grain_mask = labels == label # 生成高质量网格 - 使用较小的步长和较高的等值面水平 vertices, faces, normals, values = measure.marching_cubes( grain_mask.astype(np.float32), level=0.5, step_size=1, # 较小的步长以提高精度 allow_degenerate=False, gradient_direction='descent' ) # 创建网格对象 mesh = trimesh.Trimesh(vertices=vertices, faces=faces) # 应用真实尺度 mesh.vertices *= voxel_size # 平滑网格 mesh = mesh.smooth() # 应用PCA对齐 mesh = align_mesh(mesh) # 保存为STL文件 output_path = os.path.join(output_dir, f"KL-{index+1:03d}.stl") mesh.export(output_path, file_type='stl') print(f"已保存: {output_path}") return True except Exception as e: print(f"处理颗粒 {label} 时出错: {str(e)}") return False def align_mesh(mesh): """使用PCA对齐网格方向""" # 计算顶点的主成分 pca = PCA(n_components=3) pca.fit(mesh.vertices) # 旋转网格以使主成分与坐标轴对齐 transformed_vertices = pca.transform(mesh.vertices) # 创建新的对齐后的网格 aligned_mesh = trimesh.Trimesh(vertices=transformed_vertices, faces=mesh.faces) return aligned_mesh def visualize_results(labels, output_dir): """可视化结果""" print("生成可视化结果...") # 创建可视化目录 viz_dir = os.path.join(output_dir, "visualization") os.makedirs(viz_dir, exist_ok=True) # 生成中间切片的标签可视化 mid_slice = labels.shape[0] // 2 plt.figure(figsize=(12, 10)) plt.imshow(labels[mid_slice], cmap='nipy_spectral') plt.colorbar(label='颗粒标签') plt.title(f'中间切片 (Z={mid_slice}) 的颗粒分割结果') plt.savefig(os.path.join(viz_dir, 'segmentation_result.png'), dpi=300, bbox_inches='tight') plt.close() # 生成体积分布直方图 volumes = calculate_volumes(labels) vol_values = list(volumes.values()) plt.figure(figsize=(10, 6)) plt.hist(vol_values, bins=50, alpha=0.7, color='steelblue') plt.axvline(np.mean(vol_values), color='red', linestyle='dashed', linewidth=2, label=f'平均体积: {np.mean(vol_values):.0f}') plt.xlabel('体积 (体素数)') plt.ylabel('频率') plt.title('颗粒体积分布') plt.legend() plt.savefig(os.path.join(viz_dir, 'volume_distribution.png'), dpi=300, bbox_inches='tight') plt.close() def main(): """主函数""" start_time = time.time() # 设置警告过滤 warnings.filterwarnings("ignore", category=UserWarning) warnings.filterwarnings("ignore", category=RuntimeWarning) try: print("开始处理...") with tqdm(total=5, desc="总体进度") as pbar: # 1. 读取CT数据 ct_volume_gpu = read_tiff_sequence(input_path) pbar.update(1) # 2. 预处理CT数据 processed_volume_gpu = preprocess_ct_gpu(ct_volume_gpu) pbar.update(1) # 3. 分割砾石 labels = segment_grains_gpu(processed_volume_gpu, min_distance=3, footprint_size=3) pbar.update(1) # 4. 提取并保存砾石 extract_and_save_grains_high_quality(labels, output_dir, voxel_size, target_count) pbar.update(1) # 5. 生成可视化结果 visualize_results(labels, output_dir) pbar.update(1) total_time = time.time() - start_time print(f"\n处理完成! 总共耗时: {total_time/60:.2f} 分钟") except Exception as e: print(f"处理过程中出错: {str(e)}") import traceback traceback.print_exc() if __name__ == "__main__": main()
09-18
带开环升压转换器和逆变器的太阳能光伏系统 太阳能光伏系统驱动开环升压转换器和SPWM逆变器提供波形稳定、设计简单的交流电的模型 Simulink模型展示了一个完整的基于太阳能光伏的直流到交流电力转换系统,该系统由简单、透明、易于理解的模块构建而成。该系统从配置为提供真实直流输出电压的光伏阵列开始,然后由开环DC-DC升压转换器进行处理。升压转换器将光伏电压提高到适合为单相全桥逆变器供电的稳定直流链路电平。 逆变器使用正弦PWM(SPWM)开关来产生干净的交流输出波形,使该模型成为研究直流-交流转换基本操作的理想选择。该设计避免了闭环和MPPT的复杂性,使用户能够专注于光伏接口、升压转换和逆变器开关的核心概念。 此模型包含的主要功能: •太阳能光伏阵列在标准条件下产生~200V电压 •具有固定占空比操作的开环升压转换器 •直流链路电容器,用于平滑和稳定转换器输出 •单相全桥SPWM逆变器 •交流负载,用于观察实际输出行为 •显示光伏电压、升压输出、直流链路电压、逆变器交流波形和负载电流的组织良好的范围 •完全可编辑的结构,适合分析、实验和扩展 该模型旨在为太阳能直流-交流转换提供一个干净高效的仿真框架。布局简单明了,允许用户快速了解信号流,检查各个阶段,并根据需要修改参数。 系统架构有意保持模块化,因此可以轻松扩展,例如通过添加MPPT、动态负载行为、闭环升压控制或并网逆变器概念。该模型为进一步开发或整合到更大的可再生能源模拟中奠定了坚实的基础。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Rikka_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值