luogu 2503 & bzoj 2428

两个多星期没更新了,显然我摸了两个星期的鱼

但我已经悔改了,我觉得就算天大的事情也不能让我放弃刷题去打lol,letme!让帝!不!!!!


完蛋了啊。我写了个假的爬山又A了(

先随机一些数的位置,然后考虑拿出来一个数字丢到sum最小的那里面即可。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef double db;
 4 const db eps = 1e-6;
 5 const db delta = 0.90;
 6 const db INF = 1e99;
 7 int n,m;db a[22];db ave,ans = 1e18;
 8 db sum[22];int pos[22];
 9 db pow2(db x){return pow(x,2);}
10 void sa(){
11     memset(sum,0, sizeof(sum));
12     db now=0,T=100;
13     for(int i=1;i<=n;i++)pos[i]=rand()%m+1,sum[pos[i]]+=a[i];
14     for(int i=1;i<=m;i++)now+=pow2(sum[i]-ave);
15     while (T*delta>eps){
16         int id1 = min_element(sum+1,sum+1+m)-sum;
17         int p = rand()%n+1,id2 = pos[p];
18         if(id1==id2)continue;
19         db tmp = now;
20         now-=pow2(sum[id1]-ave)+pow2(sum[id2]-ave);
21         sum[id2]-=a[p];sum[id1]+=a[p];
22         now+=pow2(sum[id1]-ave)+pow2(sum[id2]-ave);
23         if(now>tmp){//
24             sum[id2]+=a[p];sum[id1]-=a[p];now=tmp;
25         }else{
26             pos[p]=id1;
27         }
28         T*=delta;
29     }
30     ans = min(ans, now);
31 }
32 
33 int main(){
34     scanf("%d%d",&n,&m);
35     for(int i=1;i<=n;i++){
36         scanf("%lf",&a[i]);
37         ave+=a[i];
38     }
39     ave/=m;
40     for(int i=1;i<=10000;i++) {
41         sa();
42     }
43     printf("%.2f",sqrt(ans/m));
44 }
View Code
原文地址:https://www.cnblogs.com/MXang/p/10914909.html