bzoj2428: [HAOI2006]均分数据

模拟退火。挺好理解的。然后res打成了ans一直WA一直WA。。。!!!一定要注意嗷嗷嗷一定要注意嗷嗷嗷一定要注意嗷嗷嗷。

然后我就一直卡一直卡。。。发现最少1800次的时候就可以出解了。然后我就去调T的参数。0.85/0.82都会WA。因为T的变化幅度太大。0.95/0.92都能A。

bzoj#31挺开心的。

#include<cstdio> 
#include<cstring> 
#include<cctype> 
#include<algorithm> 
#include<cmath> 
#include<ctime> 
using namespace std; 
#define rep(i,s,t) for(int i=s;i<=t;i++) 
#define dwn(i,s,t) for(int i=s;i>=t;i--) 
#define clr(x,c) memset(x,c,sizeof(x)) 
const int nmax=1e3+5; 
int a[nmax],be[nmax],b[nmax],n,m; 
double ans=1e30,sm=0; 
void SA(){ 
    double res=0,T=10000,tmp,temp;int u,v,d; 
    clr(b,0); 
    rep(i,1,n) u=rand()%m+1,be[i]=u,b[u]+=a[i]; 
    rep(i,1,m) res+=(b[i]-sm)*(b[i]-sm); 
    while(T>0.1){ 
        u=rand()%n+1;v=be[u];T*=0.9; 
        if(T>500) d=min_element(b+1,b+m+1)-b; 
        else d=rand()%m+1; 
        if(v==d) continue; 
        tmp=res; 
        res-=(b[v]-sm)*(b[v]-sm)+(b[d]-sm)*(b[d]-sm); 
        b[v]-=a[u];b[d]+=a[u]; 
        res+=(b[v]-sm)*(b[v]-sm)+(b[d]-sm)*(b[d]-sm); 
        if(res<=tmp) be[u]=d; 
        else if(rand()%10000>T) b[v]+=a[u],b[d]-=a[u],res=tmp; 
        else be[u]=d; 
    } 
    ans=min(ans,res); 
} 
int main(){ 
    srand(100000007); 
    scanf("%d%d",&n,&m); 
    rep(i,1,n) scanf("%d",&a[i]),sm+=a[i]; 
    sm/=(double)m; 
    rep(i,1,1800) SA(); 
    printf("%.2lf\n",sqrt(ans/m)); 
    return 0; 
} 

  

2428: [HAOI2006]均分数据

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 1699  Solved: 517
[Submit][Status][Discuss]

Description

已知N个正整数:A1、A2、……、An 。今要将它们分成M组,使得各组数据的数值和最平均,即各组的均方差最小。均方差公式如下:

,其中σ为均方差,是各组数据和的平均值,xi为第i组数据的数值和。

 

 

Input

第一行是两个整数,表示N,M的值(N是整数个数,M是要分成的组数)
第二行有N个整数,表示A1、A2、……、An。整数的范围是1--50。
(同一行的整数间用空格分开)

Output

这一行只包含一个数,表示最小均方差的值(保留小数点后两位数字)。

 

 

 

 

Sample Input

6 3
1 2 3 4 5 6

Sample Output

0.00

HINT

 

对于全部的数据,保证有K<=N <= 20,2<=K<=6

 

Source

[Submit][Status][Discuss]
posted @ 2016-09-22 21:54  BBChq  阅读(130)  评论(0编辑  收藏  举报