[BZOJ2428] [HAOI2006]均分数据 && 模拟退火

来源:互联网 发布:电力大数据应用 编辑:程序博客网 时间:2024/05/17 03:04

我真是*了狗了

随机数种子被卡了 我也是醉了 什么给T分段什么的 做几万次模拟退火什么的 根本想不到啊QAQ 

一晚上就被这些鬼模拟退火虐过去了

#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>#include<queue>#include<cmath>#define PF printf#define SF scanfusing namespace std;typedef long long LL;const int MAXN = 20;double Min, ave, ans = 1e30;int n, m;int A[MAXN+10], group[MAXN+10];double sum[MAXN+10];inline double Rand() {return rand() % 10000 / 10000;}inline int find_min() {int MIN = 1234567890, p;for(int i = 1; i <= m; i++) if(sum[i] < MIN) MIN = sum[i], p = i;return p;}void SA(int T) {memset(sum, 0, sizeof(sum));for(int i = 1; i <= n; i++) {group[i] = rand() % m + 1;sum[group[i]] += A[i];}double Now = 0, New;for(int i = 1; i <= m; i++) Now += (sum[i] - ave) * (sum[i] - ave);while(T > 0.1) {T *= 0.9;int x = rand() % n + 1, from = group[x], to;if(T > 500) to = find_min();else to = rand() % m + 1;if(from == to) continue;New = Now;New -= (sum[from] - ave) * (sum[from] - ave) + (sum[to] - ave) * (sum[to] - ave);sum[from] -= A[x]; sum[to] += A[x];New += (sum[from] - ave) * (sum[from] - ave) + (sum[to] - ave) * (sum[to] - ave);double dE = Now - New;if(dE > 0 || rand() % 10000 <= T) {            Now = New; group[x] = to;        }        else {            sum[from] += A[x]; sum[to] -= A[x];        }        ans = min(ans, Now);        T *= 0.97;}}int main() {srand(23333333);SF("%d%d", &n, &m);for(int i = 1; i <= n; i++) SF("%d", &A[i]), ave += A[i];ave /= 1.0 * m;for(int i = 1; i <= 20000; i++) SA(10000);PF("%.2f", sqrt(ans/m));}


0 0
原创粉丝点击