洛谷P2179 骑行川藏
什么毒瘤...
解: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 骑行川藏的更多相关文章
- bzoj 2876: [Noi2012]骑行川藏 拉格朗日数乘
2876: [Noi2012]骑行川藏 Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 1033 Solved: ...
- 高等数学(拉格朗日乘子法):NOI 2012 骑行川藏
[NOI2012] 骑行川藏 输入文件:bicycling.in 输出文件:bicycling.out 评测插件 时间限制:1 s 内存限制:128 MB NOI2012 Day1 Des ...
- BZOJ 2876 【NOI2012】 骑行川藏
题目链接:骑行川藏 听说这道题需要一些高数知识 于是膜了一发dalao的题解……然后就没了…… 不要吐槽我的精度TAT……eps设太小了就TLE,大了就Wa……我二分的边界是对着数据卡的…… 下面贴代 ...
- 【BZOJ2876】【NOI2012】骑行川藏(数学,二分答案)
[BZOJ2876][NOI2012]骑行川藏(数学,二分答案) 题面 BZOJ 题解 我们有一个很有趣的思路. 首先我们给每条边随意的赋一个初值. 当然了,这个初值不会比这条边的风速小. 那么,我们 ...
- 「NOI2012」骑行川藏
「NOI2012」骑行川藏 题目描述 蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨. 川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的 ...
- 2876: [Noi2012]骑行川藏 - BZOJ
Description 蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨.川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的体力十分有限,因 ...
- bzoj2876 [Noi2012]骑行川藏
Description 蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨.川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的体力十分有限,因 ...
- bzoj2876 [NOI2012]骑行川藏(拉格朗日乘数法)
题目描述 蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨.川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的体力十分有限,因此在每天的骑行 ...
- P2179-[NOI2012]骑行川藏【导数,二分】
正题 题目链接:https://www.luogu.com.cn/problem/P2179 题目大意 给出\(E\)和\(n\)个\(s_i,k_i,u_i\)求一个序列\(v_i\)满足 \[\s ...
随机推荐
- spring cloud feign 文件上传和文件下载
文件上传参考文档:http://blog.didispace.com/spring-cloud-starter-dalston-2-4/ 文件下载参考文档:https://blog.csdn.net/ ...
- SpringBoot学习笔记(一)入门
1.重新认识Spring 假如临危受命需要开发一个简单的基于Spring的web程序,你该做什么?可能想到一些基本的需要: 项目结构,其中可选择使用Maven或Gradle构建.其中包含例如Sprin ...
- Nginx + Keepalived实现应用高可用负载均衡功能
说明:此处仅介绍 Keepalived 实现nginx负载均衡器的高可用,关于nginx介绍和负载均衡实现可查看我的另两篇博文 Nginx负载均衡 和 Nginx配置了解 应用背景:实现高可用,避免单 ...
- Java实现"命令式"简易文本编辑器原型
源自早先想法, 打算从界面方向做些尝试. 找到个简单文本编辑器的实现: Simple Text Editor - Java Tutorials. 原本的菜单/按钮界面如下. 包括基本功能: 新建/打开 ...
- Jmeter接口测试实战-数据传递
Jmeter接口测试实战-数据传递 接口与接口之间没有关联的测试是缺乏意义和没有灵魂的,只有数据在不同接口之间传递才能勾画出业务场景重要的链路. 我们用较为通用的http/https协议,接口普遍返回 ...
- 测者的测试技术手册:分清Java的Override和Overload
Java的Override和OverloadOverride重写:子类对父类的允许访问的方法实现过程重新编写,但是 不可改变返回值和入参.重弄写的规则: 参数列表必须完全与被重写方法的相同: 返回类型 ...
- ext组件中的查询
组件中的查询依赖于组件树,往上可追溯父组件,往下可查找子组件. 组件中的查询主要包括8个方法:up.down.query.child.nextNode.nextSibiling.previoutNod ...
- 我的Windows日常——你的小电影藏好了吗?
Hello! everybody! 记得大三,第一次上我们某主任的课(我是计算机学部的),某主任上课的第一件事,点名,第二件事,忽悠我们. 具体忽悠步骤如下: 某:”同学们,这里有 ...
- 配置SSH(GNS3)
实验拓扑: -------------------------------------------配置IP过程不多啰嗦了 1.SSH配置过程 这里是用GSN3模拟器做的 --------------- ...
- 牛津初阶字典单词F-联想故事
从前有一个fable寓言,讲的是奥巴马穿着棉fabrics织物,走在去往学校的路上,他的心情fabulous极好的,绝妙的.因为他学校的facilities 设施fabulous非常棒,但有些人不喜欢 ...