什么毒瘤...

解:n = 1的,发现就是一个二次函数,解出来一个v的取值范围,选最大的即可。

n = 2的,猜测可以三分。于是先二分给第一段路多少能量,然后用上面的方法求第二段路的最短时间。注意剩余能量不足跑完第二段路的时候,返回INF。

正解是啥拉格朗日乘子法,完全搞不倒...

 /**
* There is no end though there is a start in space. ---Infinity.
* It has own power, it ruins, and it goes though there is a start also in the star. ---Finite.
* Only the person who was wisdom can read the most foolish one from the history.
* The fish that lives in the sea doesn't know the world in the land.
* It also ruins and goes if they have wisdom.
* It is funnier that man exceeds the speed of light than fish start living in the land.
* It can be said that this is an final ultimatum from the god to the people who can fight.
*
* Steins;Gate
*/ #include <bits/stdc++.h> const int N = ; double k[N], s[N], vv[N], E;
int n; namespace n1 {
inline void solve() {
double v = vv[] + sqrt(E / s[] / k[]);
printf("%.10f\n", s[] / v);
return;
}
} namespace n2 { inline double cal(double v) {
double ans = s[] / v;
double delta = k[] * s[] * (vv[] - v) * (vv[] - v);
//printf("E - delta = %.10f \n", E - delta);
double v2 = vv[] + sqrt((E - delta) / s[] / k[]);
if(v2 < ) return 1e14;
//printf("v2 %.10f = %.10f + sqrt(%.10f / %.10f / %.10f) \n", v2, vv[2], E - delta, s[2], k[2]);
//printf(" = %.10f + %.10f \n", vv[2], sqrt((E - delta) / s[2] / k[2]));
//printf("cal %.10f -> %.10f + %.10f / %.10f \n", v, ans, s[2], v2);
return ans + s[] / v2;
} inline void solve() { double l = , r = vv[] + sqrt(E / s[] / k[]);
for(int i = ; i <= ; i++) {
double mid = (l + r) / ;
//printf("l = %.10f r = %.10f \n", l, r);
double ml = mid - (r - l) / , mr = mid + (r - l) / ;
double vl = cal(ml), vr = cal(mr);
if(vl > vr) {
l = ml;
}
else {
r = mr;
}
}
printf("%.10f\n", cal(r));
return;
}
} int main() {
scanf("%d%lf", &n, &E);
for(int i = ; i <= n; i++) {
scanf("%lf%lf%lf", &s[i], &k[i], &vv[i]);
} if(n == ) {
n1::solve();
return ;
} if(n == ) {
n2::solve();
return ;
} return ;
}

40分代码

学习了一波模拟退火,突然发现这道题可能比较适合乱搞?于是开始疯狂调参最后成功在LOJ和洛谷上A掉了...

考虑如何随机化得出解。我们随机每条路的能量分配即可。

风速为负的每条路有一个能量下限。在此基础上我们把多出来的能量作为自由能量来进行分配。

初始解就是把自由能量均分...之后我们每次随机出两条路a和b,把a的若干能量给b。这里我给的能量是min(a的能量,T * c) * Rand(0, 1)

这里的c是一个参数。于是我们做到了让调整量随着温度的降低而变小。

然后瞎调一波,从0分优化到了100分......中间有很多脑洞大开改参数的过程...

最好玩的是LOJ的AC代码在洛谷上95分,洛谷的AC代码在LOJ上90分...

 // luogu-judger-enable-o2
#include <bits/stdc++.h> const int N = , INF = 0x3f3f3f3f; double k[N], s[N], vv[N], E;
int n; namespace n1 {
inline void solve() {
double v = vv[] + sqrt(E / s[] / k[]);
printf("%.10f\n", s[] / v);
return;
}
} namespace n2 { inline double cal(double v) {
double ans = s[] / v;
double delta = k[] * s[] * (vv[] - v) * (vv[] - v);
double v2 = vv[] + sqrt((E - delta) / s[] / k[]);
if(v2 < ) return 1e14;
return ans + s[] / v2;
} inline void solve() { double l = , r = vv[] + sqrt(E / s[] / k[]);
for(int i = ; i <= ; i++) {
double mid = (l + r) / ;
//printf("l = %.10f r = %.10f \n", l, r);
double ml = mid - (r - l) / , mr = mid + (r - l) / ;
double vl = cal(ml), vr = cal(mr);
if(vl > vr) {
l = ml;
}
else {
r = mr;
}
}
printf("%.10f\n", cal(r));
return;
}
} namespace Fire {
const double eps = 1e-;
double T = , dT = 0.999992;
double nowE[N], temp[N], lm[N];
int test[N]; inline int rd(int l, int r) {
return rand() % (r - l + ) + l;
} inline double Rand() {
return 1.0 * rand() / RAND_MAX;
} inline double calv(int i, double e) {
return vv[i] + sqrt(e / k[i] / s[i]);
} inline double calt(int i, double e) {
return s[i] / (vv[i] + sqrt(e / k[i] / s[i]));
} inline double init() {
for(int i = ; i <= n; i++) {
if(vv[i] < -eps) {
lm[i] = k[i] * s[i] * vv[i] * vv[i];
E -= lm[i];
}
}
double dt = E / n, ans = ;
for(int i = ; i <= n; i++) {
nowE[i] = dt;
ans += calt(i, lm[i] + nowE[i]);
}
return ans;
} inline void solve() {
double ans, fin = 1e14;
srand();
for(int A = ; A <= ; A++) {
ans = init();
fin = std::min(ans, fin);
while(T > eps) {
/// Random a new solution
int a = rd(, n), b = rd(, n);
while(a == b) {
a = rd(, n), b = rd(, n);
}
double deltaE = std::min((long double)nowE[a], (long double)T * 1e8) * Rand();
temp[a] = nowE[a] - deltaE;
temp[b] = nowE[b] + deltaE; double New = ans - calt(a, lm[a] + nowE[a]) - calt(b, lm[b] + nowE[b])
+ calt(a, lm[a] + temp[a]) + calt(b, lm[b] + temp[b]); fin = std::min(fin, New);
if(New < ans || Rand() < exp((ans - New) / T)) {
ans = New;
nowE[a] = temp[a];
nowE[b] = temp[b];
}
T = T * dT;
}
}
printf("%.10f\n", fin);
return;
}
} int main() {
scanf("%d%lf", &n, &E);
for(int i = ; i <= n; i++) {
scanf("%lf%lf%lf", &s[i], &k[i], &vv[i]);
} if(n == ) {
n1::solve();
return ;
} if(n == ) {
n2::solve();
return ;
} Fire::solve();
return ;
}

洛谷AC代码

 #include <bits/stdc++.h>

 const int N = , INF = 0x3f3f3f3f;

 double k[N], s[N], vv[N], E;
int n; namespace n1 {
inline void solve() {
double v = vv[] + sqrt(E / s[] / k[]);
printf("%.10f\n", s[] / v);
return;
}
} namespace n2 { inline double cal(double v) {
double ans = s[] / v;
double delta = k[] * s[] * (vv[] - v) * (vv[] - v);
double v2 = vv[] + sqrt((E - delta) / s[] / k[]);
if(v2 < ) return 1e14;
return ans + s[] / v2;
} inline void solve() { double l = , r = vv[] + sqrt(E / s[] / k[]);
for(int i = ; i <= ; i++) {
double mid = (l + r) / ;
//printf("l = %.10f r = %.10f \n", l, r);
double ml = mid - (r - l) / , mr = mid + (r - l) / ;
double vl = cal(ml), vr = cal(mr);
if(vl > vr) {
l = ml;
}
else {
r = mr;
}
}
printf("%.10f\n", cal(r));
return;
}
} namespace Fire {
const double eps = 1e-;
double T = , dT = 0.99999;
double nowE[N], temp[N], lm[N];
int test[N]; inline int rd(int l, int r) {
return rand() % (r - l + ) + l;
} inline double Rand() {
return 1.0 * rand() / RAND_MAX;
} inline double calv(int i, double e) {
return vv[i] + sqrt(e / k[i] / s[i]);
} inline double calt(int i, double e) {
return s[i] / (vv[i] + sqrt(e / k[i] / s[i]));
} inline double init() {
for(int i = ; i <= n; i++) {
if(vv[i] < -eps) {
lm[i] = k[i] * s[i] * vv[i] * vv[i];
E -= lm[i];
}
}
double dt = E / n, ans = ;
for(int i = ; i <= n; i++) {
nowE[i] = dt;
ans += calt(i, lm[i] + nowE[i]);
}
return ans;
} inline void solve() {
double ans, fin = 1e14;
srand();
for(int A = ; A <= ; A++) {
ans = init();
fin = std::min(ans, fin);
while(T > eps) {
/// Random a new solution
int a = rd(, n), b = rd(, n);
while(a == b) {
a = rd(, n), b = rd(, n);
}
double deltaE = std::min((long double)nowE[a], (long double)T * 1e11) * Rand();
temp[a] = nowE[a] - deltaE;
temp[b] = nowE[b] + deltaE; double New = ans - calt(a, lm[a] + nowE[a]) - calt(b, lm[b] + nowE[b])
+ calt(a, lm[a] + temp[a]) + calt(b, lm[b] + temp[b]); fin = std::min(fin, New);
if(New < ans || Rand() < exp((ans - New) / T)) {
ans = New;
nowE[a] = temp[a];
nowE[b] = temp[b];
}
T = T * dT;
}
}
printf("%.8f\n", fin);
return;
}
} int main() {
scanf("%d%lf", &n, &E);
for(int i = ; i <= n; i++) {
scanf("%lf%lf%lf", &s[i], &k[i], &vv[i]);
} if(n == ) {
n1::solve();
return ;
} if(n == ) {
n2::solve();
return ;
} Fire::solve();
return ;
}

LOJAC代码

调参心得:△T越接近1,就越慢,同时效果越好。初始温度太大可能会超时...

洛谷P2179 骑行川藏的更多相关文章

  1. bzoj 2876: [Noi2012]骑行川藏 拉格朗日数乘

    2876: [Noi2012]骑行川藏 Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 1033  Solved: ...

  2. 高等数学(拉格朗日乘子法):NOI 2012 骑行川藏

    [NOI2012] 骑行川藏 输入文件:bicycling.in   输出文件:bicycling.out   评测插件 时间限制:1 s   内存限制:128 MB NOI2012 Day1 Des ...

  3. BZOJ 2876 【NOI2012】 骑行川藏

    题目链接:骑行川藏 听说这道题需要一些高数知识 于是膜了一发dalao的题解……然后就没了…… 不要吐槽我的精度TAT……eps设太小了就TLE,大了就Wa……我二分的边界是对着数据卡的…… 下面贴代 ...

  4. 【BZOJ2876】【NOI2012】骑行川藏(数学,二分答案)

    [BZOJ2876][NOI2012]骑行川藏(数学,二分答案) 题面 BZOJ 题解 我们有一个很有趣的思路. 首先我们给每条边随意的赋一个初值. 当然了,这个初值不会比这条边的风速小. 那么,我们 ...

  5. 「NOI2012」骑行川藏

    「NOI2012」骑行川藏 题目描述 蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨. 川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的 ...

  6. 2876: [Noi2012]骑行川藏 - BZOJ

    Description 蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨.川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的体力十分有限,因 ...

  7. bzoj2876 [Noi2012]骑行川藏

    Description 蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨.川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的体力十分有限,因 ...

  8. bzoj2876 [NOI2012]骑行川藏(拉格朗日乘数法)

    题目描述 蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨.川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的体力十分有限,因此在每天的骑行 ...

  9. P2179-[NOI2012]骑行川藏【导数,二分】

    正题 题目链接:https://www.luogu.com.cn/problem/P2179 题目大意 给出\(E\)和\(n\)个\(s_i,k_i,u_i\)求一个序列\(v_i\)满足 \[\s ...

随机推荐

  1. vue-router 页面布局

    在单页面应用程序(SPA)中,有些页面的布局结构是上下两块是固定,中间内容是变化的.这时在入口处固定上下部分就可以很好的解决这一问题.有少部分页面没有上下部分或不需要(如:用户注册.登陆页面),针对这 ...

  2. 20190421-那些年使用过的CSS预处理器(CSS Preprocessor)

    写在前面的乱七八糟的前言: emmm,不得不说,早上七点是个好时间,公园里跳广场舞的大妈,街边卖菜刀看报的大爷,又不得不说,广州图书馆是个好地方,该有的安静,该有的人气,听着楼下小孩子的声音,看着周围 ...

  3. 安装可以查看PMM 源码的Go环境

    1.基础介绍 最近在搭建PMM数据库监控系统,我们知道 Prometheus 是 PMM Server 的重要组件,*_exporter是PMM Client的主要组件. 归属组件 名称 作用 Ser ...

  4. C# -- 使用Ping检查网络是否正常

    C# -- 使用Ping检查网络是否正常 需引用命名空间: using System.Net.NetworkInformation; 1. 代码实现 try { List<string> ...

  5. 如何快速搭建一个基于ServiceStack框架的web服务

    ServiceStack是一个高性能的.NET Web Service 平台,能够简化开发高性能的REST (支持JSON,XML,JSV,HTML,MsgPack,ProtoBuf,CSV等消息格式 ...

  6. C# 中利用 CRC32 值判断文件是否重复

    需要在 NuGet 中引用 Crc32.NET 包 直接贴代码了: using Force.Crc32; using System; using System.Collections.Generic; ...

  7. 2019十二省联考 Round 1 && 济南市市中心游记

    在这样一场毒瘤的省选中 这道题目无疑是命题人无私的馈赠 大量精心构造的部分分,涵盖了题目中所有涉及的算法 你可以利用这道题目,对你是否能够进入省队进行初步检查 经典的模型.较低的难度和不大的代码量,能 ...

  8. gVim编辑器 模板篇

    上文介绍了gVim的常用操作,这次总结一下我自己常用的模板. 安装和配置好gVim后,在Program Files (x86)\Vim目录下有个“_vimrc”文件,双击选择gVim软件打开,在里面添 ...

  9. ASP.NET Core RSA加密或解密

    前言 这两天主要是公司同事用到了RSA加密,事后也看了下,以为很简单,最终利用RSACryptoServiceProvider来实现RSA加密,然后大致了解到RSACryptoServiceProvi ...

  10. 序言 - PHP零基础快速入门

    我为什么要写<PHP零基础快速入门>? 原因: PHP 真心简单,适合零基础的人快速入门掌握,身边的人学习一两周上手开发的比比皆是: 市面上的文章或书籍对初学者并不友好,多半枯燥乏味,我相 ...