loj嘟嘟嘟


学完模拟退火后开始搞这道题,搞了一下午最终搞到了80分,剩下的实在不知道怎么办了……


首先肯定是把有交点的线段划分到一个集合,然后对每一个集合求一遍凸包。
然后两两合并,如果新的凸包的周长更小,那必定合并。
但有可能三个或以上合并才更优,所以上述算法肯定不行。
这时候就要模拟退火了。
每次随机合并两个,如果更优,就合并;否则有概率合并。然后我在每一次降温之前又暴力的全扫一遍尝试两两合并。
模拟退火跑到2.9秒,我又写了个一个乱搞算法,借鉴了当时rk1的写法,每次随机两个合并,直到剩一个凸包,然后取过程中的最优解。这个再跑到3.95秒。
最终搞到了80。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cmath>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<cstdlib>
  7. #include<cctype>
  8. #include<vector>
  9. #include<stack>
  10. #include<queue>
  11. #include<assert.h>
  12. #include<ctime>
  13. using namespace std;
  14. #define enter puts("")
  15. #define space putchar(' ')
  16. #define Mem(a, x) memset(a, x, sizeof(a))
  17. #define In inline
  18. typedef long long ll;
  19. typedef double db;
  20. const int INF = 0x3f3f3f3f;
  21. const db eps = 1e-13;
  22. const db DELTA = 0.99999;
  23. const int maxn = 505;
  24. inline ll read()
  25. {
  26. ll ans = 0;
  27. char ch = getchar(), last = ' ';
  28. while(!isdigit(ch)) last = ch, ch = getchar();
  29. while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
  30. if(last == '-') ans = -ans;
  31. return ans;
  32. }
  33. inline void write(ll x)
  34. {
  35. if(x < 0) x = -x, putchar('-');
  36. if(x >= 10) write(x / 10);
  37. putchar(x % 10 + '0');
  38. }
  39. In void MYFILE()
  40. {
  41. #ifndef mrclr
  42. freopen("fields.in", "r", stdin);
  43. freopen("fields.out", "w", stdout);
  44. #endif
  45. }
  46. int n;
  47. struct Point
  48. {
  49. db x, y;
  50. Point operator + (const Point& oth)const
  51. {
  52. return (Point){x + oth.x, y + oth.y};
  53. }
  54. Point operator - (const Point& oth)const
  55. {
  56. return (Point){x - oth.x, y - oth.y};
  57. }
  58. db operator * (const Point& oth)const
  59. {
  60. return x * oth.y - y * oth.x;
  61. }
  62. friend In void swap(Point& A, Point& B)
  63. {
  64. swap(A.x, B.x), swap(A.y, B.y);
  65. }
  66. friend In db dis(Point& A, Point& B)
  67. {
  68. return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y));
  69. }
  70. };
  71. struct Line
  72. {
  73. Point A, B;
  74. friend In bool cross(Line a, Line b)
  75. {
  76. db ret1 = ((a.B - a.A) * (b.A - a.A)) * ((a.B - a.A) * (b.B - a.A));
  77. db ret2 = ((b.B - b.A) * (a.A - b.A)) * ((b.B - b.A) * (a.B - b.A));
  78. return ret1 < 0 && ret2 < 0;
  79. }
  80. }l[maxn];
  81. int vis[maxn], cnt = 0;
  82. vector<Point> v[maxn];
  83. db S[maxn];
  84. Point a[maxn], P;
  85. int tot = 0, st[maxn], top = 0;
  86. In bool cmp(Point A, Point B) {return (A - P) * (B - P) > 0;}
  87. In db calc()
  88. {
  89. int pos = 1;
  90. for(int i = 2; i <= tot; ++i)
  91. if(a[i].x < a[pos].x || (fabs(a[i].x - a[pos].x) < eps && a[i].y < a[pos].y)) pos = i;
  92. if(pos ^ 1) swap(a[1], a[pos]); P = a[1];
  93. sort(a + 2, a + tot + 1, cmp);
  94. st[top = 1] = 1;
  95. for(int i = 2; i <= tot; ++i)
  96. {
  97. while(top > 1 && (a[i] - a[st[top - 1]]) * (a[st[top]] - a[st[top - 1]]) > 0) --top;
  98. st[++top] = i;
  99. }
  100. st[top + 1] = st[1];
  101. db ret = 0;
  102. for(int i = 1; i <= top; ++i) ret += dis(a[st[i]], a[st[i + 1]]);
  103. return ret;
  104. }
  105. In db TIME() {return 1.0 * clock() / CLOCKS_PER_SEC;}
  106. vector<Point> v2[maxn];
  107. db S2[maxn], sum = 0, ans = 0;
  108. int id[maxn], cnt2 = 0;
  109. In void HIA()
  110. {
  111. db T = n <= 60 ? 1000000000 : 10000000, ans2 = sum; cnt2 = 0;
  112. for(int i = 1; i <= cnt; ++i) if(vis[i] == i) id[++cnt2] = i;
  113. while(T > eps && cnt2 > 1)
  114. {
  115. if(TIME() > 2.8) return;
  116. int x = rand() % cnt2 + 1, y = rand() % cnt2 + 1;
  117. while(x == y) y = rand() % cnt2 + 1;
  118. if(x > y) swap(x, y);
  119. tot = 0;
  120. for(int i = 0; i < (int)v2[id[x]].size(); ++i) a[++tot] = v2[id[x]][i];
  121. for(int i = 0; i < (int)v2[id[y]].size(); ++i) a[++tot] = v2[id[y]][i];
  122. db tp = calc(), del = tp - S2[id[x]] - S2[id[y]];
  123. if(del < 0 || exp(-del / T) * RAND_MAX > rand())
  124. {
  125. ans2 = ans2 - S2[id[x]] - S2[id[y]] + tp;
  126. ans = min(ans, ans2);
  127. S2[id[x]] = tp;
  128. for(int i = 0; i < (int)v2[id[y]].size(); ++i) v2[id[x]].push_back(v2[id[y]][i]);
  129. for(int i = y + 1; i <= cnt2; ++i) id[i - 1] = id[i];
  130. --cnt2;
  131. }
  132. for(int i = x + 1; i <= cnt2; ++i)
  133. {
  134. if(TIME() > 2.8) return;
  135. tot = 0;
  136. for(int j = 0; j < (int)v2[id[x]].size(); ++j) a[++tot] = v2[id[x]][j];
  137. for(int j = 0; j < (int)v2[id[i]].size(); ++j) a[++tot] = v2[id[i]][j];
  138. db tp = calc();
  139. if(tp < S2[id[x]] + S2[id[i]])
  140. {
  141. ans2 = ans2 - S2[id[x]] - S2[id[i]] + tp;
  142. ans = min(ans, ans2);
  143. S2[id[x]] = tp;
  144. for(int j = 0; j < (int)v2[id[i]].size(); ++j) v2[id[x]].push_back(v2[id[i]][j]);
  145. for(int j = i + 1; j <= cnt2; ++j) id[j - 1] = id[j];
  146. --cnt2;
  147. }
  148. }
  149. T *= DELTA;
  150. }
  151. }
  152. In void HIA2()
  153. {
  154. db ans2 = sum; cnt2 = 0;
  155. for(int i = 1; i <= cnt; ++i) if(vis[i] == i) id[++cnt2] = i;
  156. while(cnt2 > 1)
  157. {
  158. if(TIME() > 3.95) return;
  159. int x = rand() % cnt2 + 1, y = rand() % cnt2 + 1;
  160. while(x == y) y = rand() % cnt2 + 1;
  161. if(x > y) swap(x, y);
  162. tot = 0;
  163. for(int i = 0; i < (int)v2[id[x]].size(); ++i) a[++tot] = v2[id[x]][i];
  164. for(int i = 0; i < (int)v2[id[y]].size(); ++i) a[++tot] = v2[id[y]][i];
  165. db tp = calc();
  166. ans2 = ans2 - S2[id[x]] - S2[id[y]] + tp;
  167. ans = min(ans, ans2);
  168. S2[id[x]] = tp;
  169. for(int i = 0; i < (int)v2[id[y]].size(); ++i) v2[id[x]].push_back(v2[id[y]][i]);
  170. for(int i = y + 1; i <= cnt2; ++i) id[i - 1] = id[i];
  171. --cnt2;
  172. }
  173. }
  174. int main()
  175. {
  176. //MYFILE();
  177. srand(20010613);
  178. n = read();
  179. for(int i = 1; i <= n; ++i)
  180. {
  181. Point A, B;
  182. A.x = read(), A.y = read(), B.x = read(), B.y = read();
  183. l[i] = (Line){A, B};
  184. }
  185. for(int i = 1; i <= n; ++i)
  186. if(!vis[i])
  187. {
  188. vis[i] = 1; ++cnt;
  189. v[cnt].push_back(l[i].A), v[cnt].push_back(l[i].B);
  190. for(int j = i + 1; j <= n; ++j)
  191. if(!vis[j] && cross(l[i], l[j]))
  192. {
  193. vis[j] = 1;
  194. v[cnt].push_back(l[j].A), v[cnt].push_back(l[j].B);
  195. }
  196. }
  197. for(int i = 1; i <= cnt; ++i)
  198. {
  199. tot = 0;
  200. for(int j = 0; j < (int)v[i].size(); ++j) a[++tot] = v[i][j];
  201. S[i] = calc();
  202. }
  203. Mem(vis, 0);
  204. for(int i = 1; i <= cnt; ++i) if(!vis[i])
  205. {
  206. vis[i] = i;
  207. for(int j = i + 1; j <= cnt; ++j) if(!vis[j])
  208. {
  209. tot = 0; db tp;
  210. for(int k = 0; k < (int)v[i].size(); ++k) a[++tot] = v[i][k];
  211. for(int k = 0; k < (int)v[j].size(); ++k) a[++tot] = v[j][k];
  212. if((tp = calc()) < S[i] + S[j])
  213. {
  214. S[i] = tp; vis[j] = i;
  215. for(int k = 0; k < (int)v[j].size(); ++k) v[i].push_back(v[j][k]);
  216. }
  217. }
  218. ans += S[i], sum += S[i];
  219. }
  220. while(TIME() < 2.9)
  221. {
  222. for(int i = 1; i <= cnt; ++i)
  223. {
  224. v2[i].clear(); S2[i] = S[i];
  225. for(int j = 0; j < (int)v[i].size(); ++j) v2[i].push_back(v[i][j]);
  226. }
  227. HIA();
  228. }
  229. while(TIME() < 3.95)
  230. {
  231. for(int i = 1; i <= cnt; ++i)
  232. {
  233. v2[i].clear(); S2[i] = S[i];
  234. for(int j = 0; j < (int)v[i].size(); ++j) v2[i].push_back(v[i][j]);
  235. }
  236. HIA2();
  237. }
  238. printf("%.8lf\n", ans);
  239. return 0;
  240. }

[CTS2019]田野(80分)的更多相关文章

  1. [关于SQL]查询成绩都大于80分的学生

    1.用一条SQL语句 查询出每门课都大于80分的学生姓名name kecheng fenshu张三 语文 81张三 数学 75李四 语文 76李四 数学 90王五 语文 81王五 数学 100王五 英 ...

  2. 用一条SQL语句查出每门课都大于80分的学生的姓名

    用一条SQL语句查出每门课都大于80分的学生的姓名,数据表结构如下: 建表SQL如下: ; -- ---------------------------- -- Table structure for ...

  3. 根据考试成绩输出对应的礼物,90分以上爸爸给买电脑,80分以上爸爸给买手机, 60分以上爸爸请吃一顿大餐,60分以下爸爸给买学习资料。 要求:该题使用多重if完成

    package com.Summer_0417.cn; import java.util.Scanner; /** * @author Summer * 根据考试成绩输出对应的礼物, * 90分以上爸 ...

  4. 案例2:用一条SQL查询出数学语文成绩都大于80分的学生姓名?

    方法1: 查出科目成绩有小于80分的学生姓名,再约束并去重学生不等于查出来的姓名 select distinct A.name from t_score A where A.name not in(s ...

  5. 第一个spring冲刺团队贡献分(80分满分)

    团队贡献分(80分满分): 李泳江 24 叶煜稳 26 谢洪跃 18 周伟雄 12

  6. 【mysql经典题目】科目成绩都大于80分\每个科目的第一名\总成绩排名

    参考:http://blog.csdn.net/lifushan123/article/details/44948135 1.查询出科目成绩都大于80分的学生的名字? drop table if EX ...

  7. SQL查询出每门课都大于80 分的学生姓名

    Course表如下: 查询出每门课都大于80 分的学生姓名有两种方法. 1.select  distinct name from Course where name not in (select di ...

  8. NOIP 2016 天天爱跑步 80分暴力

    题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 个结点 ...

  9. url映射 ccf (Java正则表达式80分解法)

    问题描述 试题编号: 201803-3 试题名称: URL映射 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 URL 映射是诸如 Django.Ruby on Rails 等 ...

随机推荐

  1. NOIP2012 DAY1 T2 国王游戏

    题目描述 恰逢 H国国庆,国王邀请n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排成一排,国王站在队伍的最前面 ...

  2. PHP学习之迭代生成器

    生成器的核心是一个yield关键字,一个生成器函数看起来像一个普通的函数,不同的是.普通函数返回一个值,而一个生成器可以yield生成许多它所需要的值.生成器函数被调用时,返回的是一个可以被遍历的对象 ...

  3. 通过python的selenium实现网站自动登陆留言

    from selenium import webdriver import time driver = webdriver.Chrome() driver.get('https://wordpress ...

  4. kubernetes 实现redis-statefulset集群

    Kubernetes 通过statefulset部署redis cluster集群 部署redis集群方式的选择 Statefulset Service&depolyment 对于redis, ...

  5. javaIO——CharArrayReader & CharArrayWriter

    上一篇学习了StringReader和StringWriter,CharArrayReader和CharArrayWriter的实现跟他们很像,拥有的方法也基本一样.区别只是,后者两个的数据操作目标是 ...

  6. XGBOOST in WIN64 安装

    参考:https://blog.csdn.net/zyghs/article/details/50897716 环境 platform:windows 10,64位 Python: Python3.7 ...

  7. Maven 依赖的作用域

    Maven的一个哲学是惯例优于配置(Convention Over Configuration), Maven默认的依赖配置项中,scope的默认值是compile,项目中经常傻傻的分不清,直接默认了 ...

  8. 对于在tinyOS中读取MPU6050数据卡死的总结

    最近这几天一直给tinyOS挂载外设,从最简单的LED.KEY,再到串口,这些都没什么大问题,无非就是先初始化tinyOS,再初始化硬件外设,接着启动tinyOS,然后tinyOS去寻找优先级最高的任 ...

  9. 原生js为页面添加爱心特效和判断手机端还是电脑端登录

    <!-- 为页面添加爱心特效 --> <script type="text/javascript"> (function (window, document ...

  10. 2.06_Python网络爬虫_正则表达式

    一:爬虫的四个主要步骤 明确目标 (要知道你准备在哪个范围或者网站去搜索) 爬 (将所有的网站的内容全部爬下来) 取 (过滤和匹配我们需要的数据,去掉没用的数据) 处理数据(按照我们想要的方式存储和使 ...