Subset

探讨了在给定整数集合中寻找子集,使子集元素和的绝对值达到最小的问题。采用折半枚举和二分查找策略,降低时间复杂度,确保在大规模数据集上的高效运行。

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

题目描述:

Given a list of N integers with absolute values no larger than 10 15, find a non empty subset of these numbers which minimizes the absolute value of the sum of its elements. In case there are multiple subsets, choose the one with fewer elements.

输入:

The input contains multiple data sets, the first line of each data set contains N <= 35, the number of elements, the next line contains N numbers no larger than 10 15 in absolute value and separated by a single space. The input is terminated with N = 0

输出:

For each data set in the input print two integers, the minimum absolute sum and the number of elements in the optimal subset.

样例输入:

1
10
3
20 100 -100
0

样例输出:

10 1
0 2

题目大意:

让你从n个数里面找任意个数(>0),使他们的和的绝对值最小,如果有多组和一样最小,输出最小和的绝对值且最小个数。

2^35,会超时,所以考虑折半枚举,减少时间复杂度,并用二分,查找绝对值最小的和

代码如下:

#include<stdio.h>
#include<algorithm>
#include<iostream>
const int maxn=1000005;
long long a[maxn];
int qq;
using namespace std;
struct node{
	long long value;
	int len;
}nod[maxn],cun[maxn];
bool cmp(node a,node b)
{
	if(a.value==b.value)return a.len<b.len;
	else return a.value<b.value;
}
int findd(long long what)
{
	int lb=-1,ub=qq,mid;
	while(ub-lb>1)
	{
		mid=(lb+ub)/2;
		if(nod[mid].value>=what)ub=mid;
		else lb=mid;
	}
	return ub;
}
int main()
{
	int n;
	while(1)
	{
		scanf("%d",&n);
		long long ans=1e15+5,res=99999;//一开始写的是ans=9999999,然后一直wrong 
		if(n==0)
		{
			break;
		}
		int i,j,k;
		for(i=0;i<n;i++)
		{
			scanf("%lld",&a[i]);
		}
		int m=n/2;
		int s=1<<(n-m);
		for(i=1;i<s;i++)
		{
			int tt=i;
			long long temp=0;
			int cnt=0;
			for(j=m;j<n;j++)
			{
				if(tt&1)
				{
					temp+=a[j];
					cnt++;
				}
				tt>>=1;
			}
			cun[i].value=temp;
			cun[i].len=cnt;
		}
		sort(cun+1,cun+s,cmp);//后半段可能有的值 
		qq=2;
		nod[0].value=0;
		nod[0].len=0;//一定要有 
		nod[1].value=cun[1].value;
		nod[1].len=cun[1].len;
		for(i=2;i<s;i++)
		{
			if(cun[i].value!=nod[qq-1].value)
			{
				nod[qq].value=cun[i].value;
				nod[qq++].len=cun[i].len;
			}
		}
		sort(nod,nod+qq,cmp);
		//减少重复 
		s=1<<m;
		for(i=0;i<s;i++)
		{
			long long temp=0;
			int cnt=0,tt=i;
			for(j=0;j<m;j++)
			{
				if(tt&1)
				{
					temp+=a[j];
					cnt++;
				}
				tt>>=1;
			}
			long long temp1=-temp;
			int pos=findd(temp1);
			int small=max(0,pos-1);
			int big=min(pos+1,qq-1);
			for(j=small;j<=big;j++)
			{
				long long en=nod[j].value+temp;
				int tm=nod[j].len+cnt;
				if(en<0)en=-en;
				if(tm==0&&en==0)
					continue;
				if(en<ans||(en==ans&&tm<res))
				{
					ans=en;
					res=tm;
				 }
			}
		}//前半段和后半段的叠加 
		printf("%lld %lld\n",ans,res);
	}
	return 0;
}
<think>嗯,用户问的是关于“train_subset”在机器学习或数据集划分中的具体含义和用途。首先,我需要确认这个术语的常见用法,因为在标准术语里可能没有直接的“train_subset”这个说法。但根据经验,用户可能指的是训练数据的一个子集。 首先,数据集通常被划分为训练集、验证集和测试集。训练集用于模型训练,验证集调整超参数,测试集评估最终性能。而“train_subset”可能是指从整个训练集中抽取的一部分数据,用于特定目的,比如加快开发调试,或者在资源有限的情况下进行初步实验。 接下来,我需要考虑用户为什么会提到这个术语。可能他们在代码中看到了这个变量名,或者在某个教程里遇到了,但不确定具体含义。这时候需要解释清楚它的定义和常见应用场景,比如数据量太大时使用子集来快速验证模型,或者在小样本学习中作为训练数据的一部分。 然后,关于用法,可能需要结合具体的机器学习框架,比如Scikit-learn中的train_test_split函数,或者TensorFlow、PyTorch中的数据加载方式。例如,使用切片操作从训练集中提取子集,或者用随机采样的方法。 还要注意用户提到的引用内容,比如引用[4]中提到了数据集的划分和转换器,这可能和特征工程或数据预处理相关。需要确保回答和这些引用内容相关联,比如提到train_test_split的使用,以及数据子集在特征工程中的应用。 另外,用户可能想知道如何实现train_subset的划分。这时候需要给出代码示例,比如使用numpy或pandas进行随机抽样,或者使用Scikit-learn的train_test_split两次,第一次分出训练集和测试集,再从训练集中分出子集。 还需要考虑可能的误区,比如子集划分时数据分布的保持,是否需要分层抽样,尤其是在分类问题中类别不平衡的情况下。这时候可以提到stratify参数的使用,确保子集和原数据分布一致。 最后,生成相关问题时要覆盖数据集划分的其他方面,比如验证集的作用,交叉验证,数据增强等,帮助用户全面理解数据处理的流程。</think>### train_subset 的定义、用法及实现 在机器学习中,**train_subset** 通常指从完整训练数据集中抽取的子集,用于特定目的(如快速实验、调试模型或资源受限时的训练)[^4]。以下是其具体含义、用途及实现方法: --- #### **1. 定义与用途** - **核心作用** 在数据集划分时,原始数据通常分为训练集(train set)、验证集(validation set)和测试集(test set)。而 **train_subset** 是从训练集中进一步抽取的子集,常见用途包括: - 加速模型开发调试(尤其是大规模数据集) - 验证算法或特征工程的初步效果 - 资源受限时(如内存不足)的轻量级训练[^3][^4] - **典型场景** - 小样本学习(Few-shot Learning) - 超参数调优的快速迭代 - 模型原型验证(Proof of Concept) --- #### **2. 实现方法** ##### **2.1 使用 Scikit-learn 划分** 通过 `train_test_split` 函数两次划分,先从完整数据中分离测试集,再从训练集中抽取子集: ```python from sklearn.model_selection import train_test_split # 原始数据划分(假设 X, y 为特征和标签) X_train_full, X_test, y_train_full, y_test = train_test_split(X, y, test_size=0.2) # 从完整训练集中抽取子集(例如取20%) X_train_subset, _, y_train_subset, _ = train_test_split( X_train_full, y_train_full, train_size=0.2, # 抽取20%作为子集 stratify=y_train_full # 保持类别分布一致(分类任务) ) ``` ##### **2.2 使用 Pandas/Numpy 抽样** 通过随机索引或切片直接抽取子集: ```python import pandas as pd import numpy as np # 假设 df 是完整训练集的 DataFrame subset_size = 1000 random_indices = np.random.choice(df.index, size=subset_size, replace=False) train_subset = df.loc[random_indices] ``` --- #### **3. 注意事项** 1. **数据分布一致性** 子集需尽量保持与完整训练集的数据分布一致(如类别比例、特征范围),可通过分层抽样(`stratify` 参数)实现[^4]。 2. **用途区分** - 训练子集(train_subset)仅用于模型训练 - 验证集(validation set)用于超参数调优 - 测试集(test set)仅用于最终评估[^3] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值