UVA12904 Load Balancing(中途相遇法)

虽然这题可以用暴力n^3过,但是还有有种n^2的方法的,枚举b,对于b,分别枚举a和c,得到对于这个b的最优解,然后从所以b中选一个最优的。

要保证字典序最小,只要从小往大枚举就好了

还有一种dp的做法,我没看懂。。。

感谢moonflyer给教我的这个思路

#include<cstdio>

#include<algorithm>

#include<cmath>

#include<cstring>



using namespace std;



const int maxn = 160+5;

int cnt[maxn];

int sum[maxn];



int main()

{

    //freopen("in.txt","r",stdin);

    int T;

    scanf("%d",&T);

    int Cas = 0;

    while(T--){

        int n;

        memset(cnt,0,sizeof(cnt));

        scanf("%d",&n);

        for(int i = 0; i < n; i++){

            int t;

            scanf("%d",&t);

            cnt[t]++;

        }

        memcpy(sum,cnt,sizeof(cnt));

        for(int i = 1; i <= 160; i++)

            sum[i] += sum[i-1];

        double ave = n/4.0;

        double bdif = 1e30;

        int besta = 0,bestb = 1,bestc = 2;

        for(int b = 1; b < 160; b++){

            double dif1 = fabs(sum[0]-ave) + fabs(sum[b]-sum[0]-ave);

            int pba = 0;

            for(int a = 1; a < b; a++){

                double ndif = fabs(sum[a]-ave)+fabs(sum[b]-sum[a]-ave);

                if(ndif<dif1){

                    dif1 = ndif; pba = a;

                }

            }

            int pbc = b+1;

            double dif2 = fabs(sum[b+1]-sum[b]) + fabs(sum[160]-sum[b+1]);

            for(int c = b+2; c<=160; c++){

                double ndif = fabs(sum[c]-sum[b]-ave)+fabs(sum[160]-sum[c]-ave);

                if(ndif < dif2){

                    dif2 = ndif; pbc = c;

                }

            }

            if(dif1+dif2<bdif){

                besta = pba; bestb = b; bestc = pbc;

                bdif = dif1+dif2;

            }

        }

        printf("Case %d: %d %d %d\n",++Cas,besta,bestb,bestc);

    }

    return 0;

}

 

你可能感兴趣的:(load)