bzoj 2428: [HAOI2006]均分数据
2018-07-15 11:26
423 查看
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 ,b ,s ;double p,f [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 [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 /m; int T=5; while(T--){ for(int i=1;i<=n;i++)b[i]=a[i]; solve(); } printf("%.2lf\n",sqrt(ans)); return 0; }
相关文章推荐
- bzoj 2428 [HAOI2006]均分数据
- [BZOJ2428][HAOI2006]均分数据(模拟退火)
- bzoj:2428: [HAOI2006]均分数据 模拟退火
- [BZOJ2428] [HAOI2006]均分数据 && 模拟退火
- bzoj2428 [HAOI2006]均分数据
- [bzoj2428]:[HAOI2006]均分数据(爬山算法)
- [BZOJ 2428] [HAOI2006] 均分数据
- [BZOJ2428][HAOI2006]均分数据
- BZOJ2428 HAOI2006均分数据(模拟退火)
- 洛谷P2503 BZOJ2428 [HAOI2006]均分数据
- BZOJ2428: [HAOI2006]均分数据 模拟退火
- bzoj 2428: [HAOI2006]均分数据
- BZOJ[2428][HAOI2006]均分数据 模拟退火
- bzoj 2428: [HAOI2006]均分数据 (模拟退火)
- BZOJ.2428.[HAOI2006]均分数据(随机化贪心/模拟退火)
- bzoj 2428: [HAOI2006]均分数据 随机化
- [HAOI2006][BZOJ2428] 均分数据
- 【HAOI2006】【BZOJ2428】均分数据
- BZOJ 2428: [HAOI2006]均分数据
- BZOJ 2428: [HAOI2006]均分数据