1. 程式人生 > >[HAOI2006]均分資料

[HAOI2006]均分資料

題目連結

          經過了14次的提交,終於正大光明的把本題A掉了。。。。

演算法:

          主要思想是模擬退火,具體操作就是,我們對於每一個生成的排列,用連續分組DP處理此情況下的最小均方差。

          dp[i][j]表示前i個數中分j組的最小均方差,dp[i][j]=min(dp[i][j],dp[k-1][j-1]+prefix[i]-prefix[j-1]-prefix[n]/m (1<=k<=i))

         (prefix是字首和應該很顯然吧。。。。。) 

Code:

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(register int i=j;i<=k;i++)
int n,m;
int co[30];
template<typename T> void chkmin(T &x,T y){x=x<y?x:y;}
template<typename T> void read(T &num){
	char c=getchar();num=0;T f=1;
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){num=(num<<3)+(num<<1)+(c^48);c=getchar();}
	num*=f;
}

int temp1[30];int temp2[30];
double dp[30][30];double prefix[30];
inline double work(int a[]){
    memset(dp,127,sizeof(dp));
    rep(i,1,n){prefix[i]=prefix[i-1]+co[a[i]];}
    dp[0][0]=0;
    rep(i,1,n){
        rep(j,1,min(i,m)){
            rep(k,1,i){
                double evenbao=(prefix[i]-prefix[k-1]-prefix[n]*1.0/m);
                chkmin(dp[i][j],dp[k-1][j-1]+evenbao*evenbao);
            }
        }
    }
    return dp[n][m];
}
inline bool Okay(double x,double y){
    if(x>=0)return true;
    return rand()<=exp((-x)/y)*RAND_MAX;
}
inline double SA(){
    double temper=10000;
    random_shuffle(temp1+1,temp1+n+1);
    rep(i,1,n){temp2[i]=temp1[i];}
    double nop1=work(temp1);double re_value=nop1;
    
    while(temper>=0.01){
        int x=rand()%n+1;int y=rand()%n+1;
        if(x==y)continue;
        swap(temp2[x],temp2[y]);
        double nop2=work(temp2);chkmin(re_value,nop2);
        if(Okay(nop1-nop2,temper)){
            nop1=nop2;swap(temp1[x],temp1[y]);
        }else{
            swap(temp2[x],temp2[y]);
        }
        temper*=0.99;
    }
    return re_value;
}

int main(){
    srand(time(NULL));
    
    read(n);read(m);
    rep(i,1,n){read(co[i]);}
    rep(i,1,n){temp1[i]=i;}
    
    double ans=INT_MAX;
    rep(i,1,72){
        chkmin(ans,SA());
 	}
	double temp=m;
    printf("%.2f\n",(sqrt(ans/temp)));
    return 0;
}