给定n个互不相同的数,让其分为两组 n1 n2 使其 交 为 空集 并 为原集合
然后使|n1-n2|的值最小,使|s2-s1|的值最大,s2 s1为 前n1 n2 个数的和
首先 题都没读懂...
其实 仔细思考了以后,不就是两个不重复的分组?
关键就是 要找到 第 n/2大的数
然后利用随机选择排序
代码如下
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <algorithm>
#define max 20
int a[max];
using namespace std;
int rand_partition(int a[],int low ,int high){
int p=(int)round(1.0*rand()/RAND_MAX*(high-low)+low);
swap(a[p],a[low]);
int pivot=a[low];
while(low<high){
while(low<high&&a[high]>=pivot) high--;
a[low]=a[high];
while(low<high&&a[low]<=pivot) low++;
a[high]=a[low];
}
a[low]=pivot;
return low;
}
void randselect(int a[],int low,int high,int s){
if(low==high) return;
int p=rand_partition(a,low,high);//p low high都是下标!可以为0
// 这个partition功能很强大啊 不仅返回了 p的最终位置
//还排了个序 坐标的都比p小 右边的都比p大
int m=p-low+1;//m是 第几大 所以要加个1 可以拿p=0 low =0 试试
if(m==s) return;
if(m<s) randselect(a,p+1,high,s-m);//m<s 随机得出的比 n/2小
else randselect(a,low,p-1,m);
}
int main(){
int n,sum=0;
printf("请输入元素个数:\n");
scanf("%d",&n);
srand((unsigned)time(NULL));
printf("分别输入%d个元素:\n",n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
sum+=a[i];
}
randselect(a,0,n-1,n/2);
int sum1=0,sum2=0;
for(int i=0;i<n/2;i++){
sum1+=a[i];
}
printf("满足要求的最大的 |S2-S1| = %d\n",sum-sum1-sum1);
return 0;
}