点此看题面

大致题意: 共进行两轮游戏,每轮每人有一个标签,标签相同的人必须到同一个点集合。求所有人总路程的最小值。

爬山算法

这道题貌似有三种做法:模拟退火高斯消元以及爬山算法

相比之下,自然是爬山算法最简单了。

实现方式

设第一轮编号为\(i\)的节点要到点\(s1_i\)集合,第二轮编号为\(i\)的节点要到点\(s2_i\)集合。

则总答案应为:

\[\sum_{i=1}^n(a_i.x-s1_{f1_i}.x)^2+(a_i.y-s1_{f1_i}.y)^2+(s1_{f1_i}.x-s2_{f2_i}.x)^2+(s1_{f1_i}.y-s2_{f2_i}.y)^2
\]

单独看其中与\(s1_{f1_i}.x\)有关的式子,我们可以发现,要想使这个式子值最小,则\(s1_{f1_i}.x\)与\(a_i.x\)和\(s2_{f2_i}.x\)的差值应越小越好。

但同一个\(s1_{f1_i}.x\)可能会受到多个\(a_i.x\)和\(s2_{f2_i}.x\)影响,所以我们需要使用爬山算法来对其慢慢修正。

具体方式就是每次将\(s1_{f1_i}.x\)减去\(\alpha*(s1_{f1_i}.x-a_i.x)-\alpha*(s1_{f1_i}.x-s2_{f2_i}.x)\)。

其中\(\alpha\)为一个较小的数,可以设为\(10^{-3}\)。

而\(s1_{f1_i}.y,s2_{f2_i}.x,s2_{f2_i}.y\)的修正同理。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 500
#define DB double
using namespace std;
int n,f1[N+5],f2[N+5];
struct Point
{
DB x,y;I Point(Con DB& a=0,Con DB& b=0):x(a),y(b){}
I friend Point operator - (Con Point& x,Con Point& y) {return Point(x.x-y.x,x.y-y.y);}
I friend Point operator * (Con DB& A,Con Point& x) {return Point(A*x.x,A*x.y);}
}a[N+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define tn(x) (x<<3)+(x<<1)
#define D isdigit(c=tc())
int f;char c,*A,*B,FI[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0,f=1;W(!D) f=c^'-'?1:-1;W(x=tn(x)+(c&15),D);x*=f;}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
}F;
class ClimbingSolver//爬山算法
{
private:
#define Dis2(A,B) (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)//计算题目中所要求的两点间距离的平方
Point s1[N+5],s2[N+5],s1_[N+5],s2_[N+5];
public:
I void Climb()
{
RI i,T=50000;Reg DB A=1e-3;W(T--)
{
for(i=1;i<=n;++i)
{
s1_[f1[i]]=s1_[f1[i]]-A*(s1[f1[i]]-a[i])-A*(s1[f1[i]]-s2[f2[i]]),//修正s1
s2_[f2[i]]=s2_[f2[i]]-A*(s2[f2[i]]-s1[f1[i]]);//修正s2
}for(i=1;i<=n;++i) s1[i]=s1_[i],s2[i]=s2_[i];//复制一遍
}
}
I DB GetAns()//求解
{
Reg DB res=0;for(RI i=1;i<=n;++i) res+=Dis2(a[i],s1[f1[i]])+Dis2(s1[f1[i]],s2[f2[i]]);//统计答案
return res;//返回答案
}
}C;
int main()
{
RI i,x,y;for(F.read(n),i=1;i<=n;++i) F.read(x,y),a[i]=Point(x,y);
for(i=1;i<=n;++i) F.read(f1[i]);for(i=1;i<=n;++i) F.read(f2[i]);//读入
return C.Climb(),printf("%.10lf",C.GetAns()),0;//求解并输出答案
}

【CCPC-Wannafly Winter Camp Day4 (Div1) J】跑跑跑路(爬山)的更多相关文章

  1. 2020 CCPC Wannafly Winter Camp Day1 C. 染色图

    2020 CCPC Wannafly Winter Camp Day1 C. 染色图 定义一张无向图 G=⟨V,E⟩ 是 k 可染色的当且仅当存在函数 f:V↦{1,2,⋯,k} 满足对于 G 中的任 ...

  2. Wannafly Winter Camp Day8(Div1,onsite) E题 Souls-like Game 线段树 矩阵乘法

    目录 Catalog Solution: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 Catalog @ Problem:传送门  Portal  原题目描述在最下面.  简单的 ...

  3. CCPC-Wannafly Winter Camp Day4 Div1 - 置置置换 - [DP]

    题目链接:https://zhixincode.com/contest/18/problem/G?problem_id=265 题目描述 wls有一个整数 $n$,他想请你算一下有多少 $1...n$ ...

  4. 【CCPC-Wannafly Winter Camp Day4 (Div1) G】置置置换(动态规划)

    点此看题面 大致题意: 求出有多少个长度为\(n\)的排列满足对于奇数位\(a_{i-1}<a_i\),对于偶数位\(a_{i-1}>a_i\). 考虑打表? 考虑每次只有一个数\(n\) ...

  5. 【CCPC-Wannafly Winter Camp Day4 (Div1) H】命命命运(概率DP)

    点此看题面 大致题意: 有\(6\)个人玩大富翁,共有\(n\)块地,进行\(500\)轮,已知每个人掷骰子掷出\(1\sim6\)的概率.当某人到达一块未被占领的地时,他可以占领它.求最后每个人占有 ...

  6. CCPC Wannafly Winter Camp Div2 部分题解

    Day 1, Div 2, Prob. B - 吃豆豆 题目大意 wls有一个\(n\)行\(m\)列的棋盘,对于第\(i\)行第\(j\)列的格子,每过\(T[i][j]\)秒会在上面出现一个糖果, ...

  7. Wannafly Winter Camp Day5 Div1 E题 Fast Kronecker Transform 转化为NTT或FFT

    目录 Catalog Solution: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 Catalog @ Problem:传送门  原题目描述在最下面.  对给定的式子算解.   ...

  8. 2020 CCPC Wannafly Winter Camp Day1 - I. K小数查询(分块)

    题目链接:K小数查询 题意:给你一个长度为$n$序列$A$,有$m$个操作,操作分为两种: 输入$x,y,c$,表示对$i\in[x,y] $,令$A_{i}=min(A_{i},c)$ 输入$x,y ...

  9. CCPC-Wannafly Winter Camp Day4 Div1 - 咆咆咆哮 - [三分+贪心]

    题目链接:https://zhixincode.com/contest/18/problem/I?problem_id=267 题目描述 输入描述 输出描述 一行一个整数表示答案. 样例输入 1 32 ...

随机推荐

  1. 移动性能测试 | 持续集成中的 Android 稳定性测试

    前言 谈到Android稳定测试,大多数会联想到使用monkey工具来做测试.google官方提供了monkey工具,可以很快速点击被应用,之前我有一篇帖子提到了monkey工具的使用,详见: htt ...

  2. 线程池ThreadPoolExecutor分析: 线程池是什么时候创建线程的,队列中的任务是什么时候取出来的?

    带着几个问题进入源码分析: 1. 线程池是什么时候创建线程的? 2. 任务runnable task是先放到core到maxThread之间的线程,还是先放到队列? 3. 队列中的任务是什么时候取出来 ...

  3. Eclipse + Git + 码云

    1. 进入码云个人首页 点击自己的名称即可 2. 添加一个项目 3. 在Eclipse中创建一个本地Git Eclipse不建议git目录创建在项目的目录下,因此另选一个目录作为本地Git目录 选择一 ...

  4. (转)AIX修改系统时区的3种方法和AIX 时间问题(夏令时)

    原文:http://blog.csdn.net/fuwencaho/article/details/28267283 http://www.wo81.com/tec/os/aix/2014-04-30 ...

  5. LeetCode 454.四数相加 II(C++)

    给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0. 为了使问题简单化,所有的 A ...

  6. Kudu的概念术语

    不多说,直接上干货! Columnar Data Store(列式数据存储) Kudu 是一个 columnar data store(列式数据存储).列式数据存储在强类型列中.由于几个原因,通过适当 ...

  7. pat1082. Read Number in Chinese (25)

    1082. Read Number in Chinese (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yu ...

  8. .net 视图格式化

    昨天在做一个功能,要在界面上按照规定的格式显示一个时间,如果直接在expression那里格式化的话(如下:) @Html.DisplayFor(c => Convert.ToDateTime( ...

  9. checkbox判断选中的三种方法

    方法一: if ($("#checkbox-id")get(0).checked) {     // do something } 方法二: if($('#checkbox-id' ...

  10. 异步请求返回json对象

    后台mvc: var result = new { flag = ture, eMail = "949096562@qq.com"}; if (result.flag) { ret ...