• bzoj 2428: [HAOI2006]均分数据


    Description

    Solution

    对于一种确定的排列,我们可以用 (O(n^2*k))(DP) 算出最优划分的方法
    但是排列需要枚举,我们可以考虑退火
    每一次交换两个元素,跑一边 (DP) 求答案即可

    #include<bits/stdc++.h>
    #define sqr(x) ((x)*(x))
    using namespace std;
    const int N=25;
    inline int rd(int l,int r){return l+rand()%(r-l+1);}
    int n,m,a[N],b[N],s[N];double p,f[N][7],inf=1e15;
    inline double calc(){
    	f[0][0]=0;
    	for(int i=1;i<=n;i++)s[i]=s[i-1]+b[i],f[i][0]=inf;
    	for(int j=1;j<=m;j++)
    		for(int i=1;i<=n;i++){
    			f[i][j]=inf;
    			for(int k=0;k<i;k++)
    				f[i][j]=min(f[i][j],f[k][j-1]+sqr(s[i]-s[k]-p));
    		}
    	return f[n][m]/m;
    }
    double maxt=100000,mint=1e-15,Down=0.993,ans=inf;
    inline void solve(){
    	double t=maxt,tans,sans=inf;
    	while(t>mint){
    		int x=rd(1,n-1),y=rd(x+1,n);
    		swap(b[x],b[y]);
    		tans=calc();
    		if(tans<sans)sans=tans;
    		else if(exp((ans-tans)/t)*RAND_MAX<rand())swap(b[x],b[y]);
    		else sans=tans;
    		ans=min(ans,sans);t*=Down;
    	}
    	ans=min(ans,sans);
    }
    int main(){
      freopen("pp.in","r",stdin);
      freopen("pp.out","w",stdout);
      srand(19260859);
      cin>>n>>m;
      for(int i=1;i<=n;i++)cin>>a[i],s[i]=s[i-1]+a[i];
      p=(double)s[n]/m;
      int T=5;
      while(T--){
    	  for(int i=1;i<=n;i++)b[i]=a[i];
    	  solve();
      }
      printf("%.2lf
    ",sqrt(ans));
      return 0;
    }
    
    
  • 相关阅读:
    Jquery复习DAY1(jQuery 选择器 jQuery 样式操作 jQuery 效果)
    git知识
    简单分析vue计算属性和methods方法的区别
    vue生命周期
    elementUI的级联选择器Cascader 高度不匹配问题高度溢出错误
    .Net Core3.1 常用的服务注入
    判断是否为AJAX请求
    JWT权限验证
    CodeSmith介绍
    常见ORM介绍
  • 原文地址:https://www.cnblogs.com/Yuzao/p/8719291.html
Copyright © 2020-2023  润新知