【codevs1959】拔河比赛 随机化贪心

题目描述 Description

一个学校举行拔河比赛,所有的人被分成了两组,每个人必须(且只能够)在其中的一组,要求两个组的人数相差不能超过1,且两个组内的所有人体重加起来尽可能地接近。

输入描述 Input Description

数据的第1行是一个n,表示参加拔河比赛的总人数,n<=100,接下来的n行表示第1到第n个人的体重,每个人的体重都是整数(1<=weight<=450)。

输出描述 Output Description

包含两个整数:分别是两个组的所有人的体重和,用一个空格隔开。注意如果这两个数不相等,则请把小的放在前面输出。

样例输入 Sample Input

3
100
90
200

样例输出 Sample Output

190 200

DP?
随机化贪心!!

所谓随机化贪心,就是:如果一个贪心,正确的概率只有0.1%,但你连续做100000次后,答案会越来越逼近正解!!这样,只需要反复做那个贪心,AC的几率就会非常非常高!!

【codevs1959】拔河比赛 随机化贪心_第1张图片

随机化大法好!!

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<ctime>
using namespace std;
const int SIZE=10010;
const int INF=233333333;
int num[SIZE];

int sum1=0,sum2=INF,n;

void randnum()
{
    for(int i=1;i<=n;i++)
    {
        int x=rand()%n+1;
        while(x==i) x=rand()%n+1;    
        swap(num[i],num[x]);
    }
}

void getans()
{
    int ans1=num[1],ans2=0,t1=1,t2=0;
    for(int i=2;i<=n;i++)
    {
        if(t1==t2-1)
            ans1+=num[i],t1++;
        else 
            ans2+=num[i],t2++;
    }   
    if(ans1>ans2) swap(ans1,ans2); 
    if(abs(ans1-ans2)<abs(sum1-sum2))
        sum1=ans1,sum2=ans2;
}

int main()
{
    srand(time(0));
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&num[i]);
    }
    for(int i=1;i<=100000;i++)
    {
        getans();
        randnum();
    }
    printf("%d %d",sum1,sum2);
    return 0;
}

你可能感兴趣的:(贪心,随机化,玄学)