蓝桥杯 算法训练 娜神平衡

这是一道关于算法的编程题目,名为'娜神平衡'。题目要求将一组不等的数分成两组,使得两组数的和之差不超过特定值r。通过递归方法,找出符合条件的分组策略,并按指定格式输出结果。输入包含数的个数n和限制值r,以及一组数,输出则是两组数的分组。

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

蓝桥杯 算法训练 娜神平衡

题目描述

  • 资源限制
    时间限制:1.0s 内存限制:256.0MB
  • 问题描述
    娜娜是一个特别可爱的女孩子,作为学神的她最近在情感方面出现了一点点小问题。
    她暗恋的琦琦是一名学霸,他只喜欢长得漂亮和学习很好的女生。
    娜娜学习确实很神,但是她在琦琦面前却总是表现不出平时的神力。
    琦琦感受到了娜娜对他的爱,但是他还是觉得娜娜的学习并不是特别好,于是他出了一道题给娜娜。
    “娜娜,我们之间的关系需要在不断深入的同时保持一定的平衡,不可以你总是强势或者我总是弱势。”
    琦琦给了娜娜一些两两不等的数,希望娜娜能把这些数分成两组A和B,满足以下条件:
    1:每一次只能操作一个数,即只取出一个数分入A中或B中;
    2:每一次操作完成后,A中数之和与B中数之和的差不能超过r。
    新时代的丘比特们啊,帮帮娜娜吧!
  • 输入格式
    输入共两行。
    第一行包括两个正整数n和r,n表示琦琦一共给了n个数,r的意义见题目描述。
    第二行包括n个正整数,分别表示琦琦给的n个数。
  • 输出格式
    输出共两行,分别把A与B两组数按从小到大输出。
    注意输入中n个数的第一个必须分入A组。
    琦琦保证这样的输出唯一。
  • 样例输入
    4 10
    9 6 4 20
  • 样例输出
    4 6 9
    20
  • 样例说明
    先把4和6先后分入A组,再把20分入B组,最后把9分入A组。
  • 数据规模和约定
    很小,真的很小。

方案1 递归

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int n;		//n个正整数 
int r;		//两组数字和之差不能超过r
vector<int> L;	//存放左组数字 
vector<int> R;	//存放右组数字 

//函数功能:从小到大打印数组 
void g(vector<int> vc){
	sort(vc.begin(), vc.end());
	for(int i=0; i<vc.size(); i++){
		cout<<vc[i]<<" ";
	}
	cout<<endl;
}

//函数功能:左组数字L[], 右组数字R[],  保证两者和之差的绝对值 abs(d) < r ,  返回是否找到这样的两组数字 , 并按要求打印 
bool f(vector<int> L, vector<int> R, int nums[], bool flag[], int d, int r, int n){
	//两者和之差的绝对值 abs(d) > r , 不合题意, 回溯 
	if(abs(d)>r){
		return 0;
	}
	
	//全部分完,按要求打印两组数 
	if(L.size() + R.size() == n){
		//查找第一个数是否在L中 
		int i;
		for(i=0; i<L.size(); i++){
			if(L[i]==nums[0]){
				//在L中,先打印L 
				g(L);
				break;
			}
		}
		g(R);
		//不在L中,先打印R 
		if(i==L.size()){
			g(L);
		}
		return 1;
	}
	
	int i;
	//遍历每一个数 
	for(i=0; i<n; i++){
		//如果该数字未被使用 , 则该数字有3种情况 
		if(!flag[i]){
			flag[i] = true;		//标记使用 
			
			//1.放L组 
			L.push_back(nums[i]);		//放进去 
			//如果符合要求, 结束递归 
			if(f(L, R, nums, flag, d+nums[i], r, n)){
				break;
			}	
			//不符合要求, 恢复现场 
			L.pop_back();		//拿出来 
			
			//2.放R组 
			R.push_back(nums[i]);       //放进去 
			//如果符合要求, 结束递归 
			if(f(L, R, nums, flag, d-nums[i], r, n)){
				break;
			}
			//不符合要求, 恢复现场 
			R.pop_back();       //拿出来 
			
			flag[i] = false;	//恢复现场 
			
			//3.都不放 
		}
	}

	return !(i==n);
}


int main(){	
	cin>>n>>r;
	int nums[n];				//存放n个数 
	bool flag[n];				//标记第i+1个数是否被使用 
	//初始化标记 
	for(int i=0; i<n; i++){
		flag[i] = 0;
	}
	
	for(int i=0; i<n; i++){
		cin >> nums[i];
	} 

	f(L, R, nums, flag, 0, r, n);

	return 0; 
} 

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值