虽然这题可以用暴力n^3过,但是还有有种n^2的方法的,枚举b,对于b,分别枚举a和c,得到对于这个b的最优解,然后从所以b中选一个最优的。
要保证字典序最小,只要从小往大枚举就好了
感谢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; }