loj嘟嘟嘟


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


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

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
#include<assert.h>
#include<ctime>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-13;
const db DELTA = 0.99999;
const int maxn = 505;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
}
In void MYFILE()
{
#ifndef mrclr
freopen("fields.in", "r", stdin);
freopen("fields.out", "w", stdout);
#endif
} int n;
struct Point
{
db x, y;
Point operator + (const Point& oth)const
{
return (Point){x + oth.x, y + oth.y};
}
Point operator - (const Point& oth)const
{
return (Point){x - oth.x, y - oth.y};
}
db operator * (const Point& oth)const
{
return x * oth.y - y * oth.x;
}
friend In void swap(Point& A, Point& B)
{
swap(A.x, B.x), swap(A.y, B.y);
}
friend In db dis(Point& A, Point& B)
{
return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y));
}
};
struct Line
{
Point A, B;
friend In bool cross(Line a, Line b)
{
db ret1 = ((a.B - a.A) * (b.A - a.A)) * ((a.B - a.A) * (b.B - a.A));
db ret2 = ((b.B - b.A) * (a.A - b.A)) * ((b.B - b.A) * (a.B - b.A));
return ret1 < 0 && ret2 < 0;
}
}l[maxn]; int vis[maxn], cnt = 0;
vector<Point> v[maxn];
db S[maxn]; Point a[maxn], P;
int tot = 0, st[maxn], top = 0;
In bool cmp(Point A, Point B) {return (A - P) * (B - P) > 0;}
In db calc()
{
int pos = 1;
for(int i = 2; i <= tot; ++i)
if(a[i].x < a[pos].x || (fabs(a[i].x - a[pos].x) < eps && a[i].y < a[pos].y)) pos = i;
if(pos ^ 1) swap(a[1], a[pos]); P = a[1];
sort(a + 2, a + tot + 1, cmp);
st[top = 1] = 1;
for(int i = 2; i <= tot; ++i)
{
while(top > 1 && (a[i] - a[st[top - 1]]) * (a[st[top]] - a[st[top - 1]]) > 0) --top;
st[++top] = i;
}
st[top + 1] = st[1];
db ret = 0;
for(int i = 1; i <= top; ++i) ret += dis(a[st[i]], a[st[i + 1]]);
return ret;
} In db TIME() {return 1.0 * clock() / CLOCKS_PER_SEC;} vector<Point> v2[maxn];
db S2[maxn], sum = 0, ans = 0;
int id[maxn], cnt2 = 0;
In void HIA()
{
db T = n <= 60 ? 1000000000 : 10000000, ans2 = sum; cnt2 = 0;
for(int i = 1; i <= cnt; ++i) if(vis[i] == i) id[++cnt2] = i;
while(T > eps && cnt2 > 1)
{
if(TIME() > 2.8) return;
int x = rand() % cnt2 + 1, y = rand() % cnt2 + 1;
while(x == y) y = rand() % cnt2 + 1;
if(x > y) swap(x, y);
tot = 0;
for(int i = 0; i < (int)v2[id[x]].size(); ++i) a[++tot] = v2[id[x]][i];
for(int i = 0; i < (int)v2[id[y]].size(); ++i) a[++tot] = v2[id[y]][i];
db tp = calc(), del = tp - S2[id[x]] - S2[id[y]];
if(del < 0 || exp(-del / T) * RAND_MAX > rand())
{
ans2 = ans2 - S2[id[x]] - S2[id[y]] + tp;
ans = min(ans, ans2);
S2[id[x]] = tp;
for(int i = 0; i < (int)v2[id[y]].size(); ++i) v2[id[x]].push_back(v2[id[y]][i]);
for(int i = y + 1; i <= cnt2; ++i) id[i - 1] = id[i];
--cnt2;
}
for(int i = x + 1; i <= cnt2; ++i)
{
if(TIME() > 2.8) return;
tot = 0;
for(int j = 0; j < (int)v2[id[x]].size(); ++j) a[++tot] = v2[id[x]][j];
for(int j = 0; j < (int)v2[id[i]].size(); ++j) a[++tot] = v2[id[i]][j];
db tp = calc();
if(tp < S2[id[x]] + S2[id[i]])
{
ans2 = ans2 - S2[id[x]] - S2[id[i]] + tp;
ans = min(ans, ans2);
S2[id[x]] = tp;
for(int j = 0; j < (int)v2[id[i]].size(); ++j) v2[id[x]].push_back(v2[id[i]][j]);
for(int j = i + 1; j <= cnt2; ++j) id[j - 1] = id[j];
--cnt2;
}
}
T *= DELTA;
}
}
In void HIA2()
{
db ans2 = sum; cnt2 = 0;
for(int i = 1; i <= cnt; ++i) if(vis[i] == i) id[++cnt2] = i;
while(cnt2 > 1)
{
if(TIME() > 3.95) return;
int x = rand() % cnt2 + 1, y = rand() % cnt2 + 1;
while(x == y) y = rand() % cnt2 + 1;
if(x > y) swap(x, y);
tot = 0;
for(int i = 0; i < (int)v2[id[x]].size(); ++i) a[++tot] = v2[id[x]][i];
for(int i = 0; i < (int)v2[id[y]].size(); ++i) a[++tot] = v2[id[y]][i];
db tp = calc();
ans2 = ans2 - S2[id[x]] - S2[id[y]] + tp;
ans = min(ans, ans2);
S2[id[x]] = tp;
for(int i = 0; i < (int)v2[id[y]].size(); ++i) v2[id[x]].push_back(v2[id[y]][i]);
for(int i = y + 1; i <= cnt2; ++i) id[i - 1] = id[i];
--cnt2;
}
} int main()
{
//MYFILE();
srand(20010613);
n = read();
for(int i = 1; i <= n; ++i)
{
Point A, B;
A.x = read(), A.y = read(), B.x = read(), B.y = read();
l[i] = (Line){A, B};
}
for(int i = 1; i <= n; ++i)
if(!vis[i])
{
vis[i] = 1; ++cnt;
v[cnt].push_back(l[i].A), v[cnt].push_back(l[i].B);
for(int j = i + 1; j <= n; ++j)
if(!vis[j] && cross(l[i], l[j]))
{
vis[j] = 1;
v[cnt].push_back(l[j].A), v[cnt].push_back(l[j].B);
}
}
for(int i = 1; i <= cnt; ++i)
{
tot = 0;
for(int j = 0; j < (int)v[i].size(); ++j) a[++tot] = v[i][j];
S[i] = calc();
}
Mem(vis, 0);
for(int i = 1; i <= cnt; ++i) if(!vis[i])
{
vis[i] = i;
for(int j = i + 1; j <= cnt; ++j) if(!vis[j])
{
tot = 0; db tp;
for(int k = 0; k < (int)v[i].size(); ++k) a[++tot] = v[i][k];
for(int k = 0; k < (int)v[j].size(); ++k) a[++tot] = v[j][k];
if((tp = calc()) < S[i] + S[j])
{
S[i] = tp; vis[j] = i;
for(int k = 0; k < (int)v[j].size(); ++k) v[i].push_back(v[j][k]);
}
}
ans += S[i], sum += S[i];
}
while(TIME() < 2.9)
{
for(int i = 1; i <= cnt; ++i)
{
v2[i].clear(); S2[i] = S[i];
for(int j = 0; j < (int)v[i].size(); ++j) v2[i].push_back(v[i][j]);
}
HIA();
}
while(TIME() < 3.95)
{
for(int i = 1; i <= cnt; ++i)
{
v2[i].clear(); S2[i] = S[i];
for(int j = 0; j < (int)v[i].size(); ++j) v2[i].push_back(v[i][j]);
}
HIA2();
}
printf("%.8lf\n", ans);
return 0;
}

[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. postman的安装与使用方法介绍

    软件介绍 在我们平时开发中,特别是需要与接口打交道时,无论是写接口还是用接口,拿到接口后肯定都得提前测试一下,这样的话就非常需要有一个比较给力的Http请求模拟工具,现在流行的这种工具也挺多的,像火狐 ...

  2. 【leetcode】287. 寻找重复数

    题目链接:传送门 题目描述: 给定一个数组 nums 包含 n + 1 个整数,每个整数在 1 到 n 之间,包括 1 和 n.现在假设数组中存在一个重复的数字,找到该重复的数字. 注意 不能修改数组 ...

  3. shell习题第18题:检查新文件

    [题目要求] 有一台服务器作为web应用,有一个目录(/data/web/attachment)不定时会被用户上传新的文件,但是不知道什么时候会被上传.所以,需要我们每5分钟做一次检测是否有新文件生成 ...

  4. git、git bash、git shell

    git 一个快速的分布式版本控制系统(工具),支持该工具的网站有Github等. shell 是linux.unix系统的外壳(区别于核),用于输入并执行命令(命令解析器). 它类似于DOS下的com ...

  5. image的路径写法格式

    if (MapGrid.Visibility == Visibility.Visible) {      this.MapGrid.Visibility = Visibility.Collapsed; ...

  6. Nginx安装与配置【转】

    原文:linux之nginx 作者;海燕. 一.nginx Ngix是web服务器,跟apache一样,它可以做动态请求转发.web端负载均衡.反向代理等等: tomcat是应用服务器,当然如果非用逼 ...

  7. 分布式全局ID的几种生成方案

    前言 在互联网的业务系统中,涉及到各种各样的ID,如在支付系统中就会有支付ID.退款ID等. 那一般生成ID都有哪些解决方案呢?特别是在复杂的分布式系统业务场景中,我们应该采用哪种适合自己的解决方案是 ...

  8. 一个SAP顾问的回忆:我过去很胖!

    去年也是这个时候,SAP成都研究院体育界大神邓阳,曾经赏脸在Jerry这个公众号上赐文一篇,介绍了他和围绕在他身边的一群小伙伴们的体育故事:SAP成都研究院的体育故事 而今天文章的主角则是SAP成都研 ...

  9. TCP的keepalive和应用层的heart

    从长链接说起 TCP是长链接的,也就是说连接建立后,及时数年没有通信连接仍然存在.这样做的好处是:免去了DNS解析的时间,连接建立等时间,大大加快了请求的速度,同时也有利于接受服务器的实时消息.但前提 ...

  10. Maven 基础概念

    Project:任何你想构建的事务Maven都可以认为它们是工程,这些工程被定义为工程对象模型(project Object Model POM) 一个工程可以依赖其他的工程,一个工程也可以由多个子工 ...