给出每个学生的学分。 将学生按学分分成四组,使得sigma (sumi-n/4)最小。 算法: 折半枚举
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <string> 7 #include <vector> 8 #include <set> 9 #include <map> 10 #include <stack> 11 #include <queue> 12 #include <sstream> 13 #include <iomanip> 14 using namespace std; 15 typedef long long LL; 16 const int INF=0x4fffffff; 17 const int EXP=1e-5; 18 const int MS=161; 19 20 int num[MS]; // 学分为i的人数 21 int sum[MS]; // 学分<=i的人数 22 23 int main() 24 { 25 int T,kase=1,n,x; 26 scanf("%d",&T); 27 while(T--) 28 { 29 memset(num,0,sizeof(num)); 30 memset(sum,0,sizeof(sum)); 31 scanf("%d",&n); 32 for(int i=0;i<n;i++) 33 { 34 scanf("%d",&x); 35 num[x]++; 36 } 37 sum[0]=num[0]; // note: sum[0]!=0; 38 for(int i=1;i<MS;i++) 39 sum[i]=sum[i-1]+num[i]; 40 // 折半枚举 41 int ansa,ansb,ansc; 42 int ta,tc; 43 double sum1,sum2,sum3=INF; 44 double ave=double(n)/4.0; 45 for(int b=1;b<MS-2;b++) 46 { 47 sum1=INF*1.0; 48 sum2=INF*1.0; 49 for(int a=0;a<b;a++) 50 { 51 double t=fabs(double(sum[a])-ave)+fabs(double(sum[b]-sum[a])-ave); 52 if(t<sum1) 53 { 54 sum1=t; 55 ta=a; 56 } 57 } 58 59 for(int c=b+1;c<MS-1;c++) 60 { 61 double t=fabs(double(sum[c]-sum[b])-ave)+fabs(double(sum[MS-1]-sum[c])-ave); 62 if(t<sum2) 63 { 64 sum2=t; 65 tc=c; 66 } 67 } 68 if(sum1+sum2<sum3) 69 { 70 sum3=sum1+sum2; 71 ansa=ta; 72 ansb=b; 73 ansc=tc; 74 } 75 } 76 printf("Case %d: %d %d %d\n",kase++,ansa,ansb,ansc); 77 } 78 return 0; 79 }
时间: 2024-12-30 03:19:32