什么毒瘤...

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

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

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

 1 /**
 2  * There is no end though there is a start in space. ---Infinity.
 3  * It has own power, it ruins, and it goes though there is a start also in the star. ---Finite.
 4  * Only the person who was wisdom can read the most foolish one from the history.
 5  * The fish that lives in the sea doesn't know the world in the land.
 6  * It also ruins and goes if they have wisdom.
 7  * It is funnier that man exceeds the speed of light than fish start living in the land.
 8  * It can be said that this is an final ultimatum from the god to the people who can fight.
 9  *
10  * Steins;Gate
11  */
12
13 #include <bits/stdc++.h>
14
15 const int N = 10010;
16
17 double k[N], s[N], vv[N], E;
18 int n;
19
20 namespace n1 {
21     inline void solve() {
22         double v = vv[1] + sqrt(E / s[1] / k[1]);
23         printf("%.10f\n", s[1] / v);
24         return;
25     }
26 }
27
28 namespace n2 {
29
30     inline double cal(double v) {
31         double ans = s[1] / v;
32         double delta = k[1] * s[1] * (vv[1] - v) * (vv[1] - v);
33         //printf("E - delta = %.10f \n", E - delta);
34         double v2 = vv[2] + sqrt((E - delta) / s[2] / k[2]);
35         if(v2 < 0) return 1e14;
36         //printf("v2 %.10f = %.10f + sqrt(%.10f / %.10f / %.10f) \n", v2, vv[2], E - delta, s[2], k[2]);
37         //printf("     =  %.10f + %.10f \n", vv[2], sqrt((E - delta) / s[2] / k[2]));
38         //printf("cal %.10f ->  %.10f + %.10f / %.10f \n", v, ans, s[2], v2);
39         return ans + s[2] / v2;
40     }
41
42     inline void solve() {
43
44         double l = 0, r = vv[1] + sqrt(E / s[1] / k[1]);
45         for(int i = 1; i <= 100; i++) {
46             double mid = (l + r) / 2;
47             //printf("l = %.10f r = %.10f \n", l, r);
48             double ml = mid - (r - l) / 6, mr = mid + (r - l) / 6;
49             double vl = cal(ml), vr = cal(mr);
50             if(vl > vr) {
51                 l = ml;
52             }
53             else {
54                 r = mr;
55             }
56         }
57         printf("%.10f\n", cal(r));
58         return;
59     }
60 }
61
62 int main() {
63     scanf("%d%lf", &n, &E);
64     for(int i = 1; i <= n; i++) {
65         scanf("%lf%lf%lf", &s[i], &k[i], &vv[i]);
66     }
67
68     if(n == 1) {
69         n1::solve();
70         return 0;
71     }
72
73     if(n == 2) {
74         n2::solve();
75         return 0;
76     }
77
78     return 0;
79 }

40分代码

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

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

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

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

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

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

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

  1 // luogu-judger-enable-o2
  2 #include <bits/stdc++.h>
  3
  4 const int N = 10010, INF = 0x3f3f3f3f;
  5
  6 double k[N], s[N], vv[N], E;
  7 int n;
  8
  9 namespace n1 {
 10     inline void solve() {
 11         double v = vv[1] + sqrt(E / s[1] / k[1]);
 12         printf("%.10f\n", s[1] / v);
 13         return;
 14     }
 15 }
 16
 17 namespace n2 {
 18
 19     inline double cal(double v) {
 20         double ans = s[1] / v;
 21         double delta = k[1] * s[1] * (vv[1] - v) * (vv[1] - v);
 22         double v2 = vv[2] + sqrt((E - delta) / s[2] / k[2]);
 23         if(v2 < 0) return 1e14;
 24         return ans + s[2] / v2;
 25     }
 26
 27     inline void solve() {
 28
 29         double l = 0, r = vv[1] + sqrt(E / s[1] / k[1]);
 30         for(int i = 1; i <= 100; i++) {
 31             double mid = (l + r) / 2;
 32             //printf("l = %.10f r = %.10f \n", l, r);
 33             double ml = mid - (r - l) / 6, mr = mid + (r - l) / 6;
 34             double vl = cal(ml), vr = cal(mr);
 35             if(vl > vr) {
 36                 l = ml;
 37             }
 38             else {
 39                 r = mr;
 40             }
 41         }
 42         printf("%.10f\n", cal(r));
 43         return;
 44     }
 45 }
 46
 47 namespace Fire {
 48     const double eps = 1e-13;
 49     double T = 1, dT = 0.999992;
 50     double nowE[N], temp[N], lm[N];
 51     int test[N];
 52
 53     inline int rd(int l, int r) {
 54         return rand() % (r - l + 1) + l;
 55     }
 56
 57     inline double Rand() {
 58         return 1.0 * rand() / RAND_MAX;
 59     }
 60
 61     inline double calv(int i, double e) {
 62         return vv[i] + sqrt(e / k[i] / s[i]);
 63     }
 64
 65     inline double calt(int i, double e) {
 66         return s[i] / (vv[i] + sqrt(e / k[i] / s[i]));
 67     }
 68
 69     inline double init() {
 70         for(int i = 1; i <= n; i++) {
 71             if(vv[i] < -eps) {
 72                 lm[i] = k[i] * s[i] * vv[i] * vv[i];
 73                 E -= lm[i];
 74             }
 75         }
 76         double dt = E / n, ans = 0;
 77         for(int i = 1; i <= n; i++) {
 78             nowE[i] = dt;
 79             ans += calt(i, lm[i] + nowE[i]);
 80         }
 81         return ans;
 82     }
 83
 84     inline void solve() {
 85         double ans, fin = 1e14;
 86         srand(69);
 87         for(int A = 1; A <= 1; A++) {
 88             ans = init();
 89             fin = std::min(ans, fin);
 90             while(T > eps) {
 91                 /// Random a new solution
 92                 int a = rd(1, n), b = rd(1, n);
 93                 while(a == b) {
 94                     a = rd(1, n), b = rd(1, n);
 95                 }
 96                 double deltaE = std::min((long double)nowE[a], (long double)T * 1e8) * Rand();
 97                 temp[a] = nowE[a] - deltaE;
 98                 temp[b] = nowE[b] + deltaE;
 99
100                 double New = ans - calt(a, lm[a] + nowE[a]) - calt(b, lm[b] + nowE[b])
101                                  + calt(a, lm[a] + temp[a]) + calt(b, lm[b] + temp[b]);
102
103                 fin = std::min(fin, New);
104                 if(New < ans || Rand() < exp((ans - New) / T)) {
105                     ans = New;
106                     nowE[a] = temp[a];
107                     nowE[b] = temp[b];
108                 }
109                 T = T * dT;
110             }
111         }
112         printf("%.10f\n", fin);
113         return;
114     }
115 }
116
117 int main() {
118     scanf("%d%lf", &n, &E);
119     for(int i = 1; i <= n; i++) {
120         scanf("%lf%lf%lf", &s[i], &k[i], &vv[i]);
121     }
122
123     if(n == 1) {
124         n1::solve();
125         return 0;
126     }
127
128     if(n == 2) {
129         n2::solve();
130         return 0;
131     }
132
133     Fire::solve();
134     return 0;
135 }

洛谷AC代码

  1 #include <bits/stdc++.h>
  2
  3 const int N = 10010, INF = 0x3f3f3f3f;
  4
  5 double k[N], s[N], vv[N], E;
  6 int n;
  7
  8 namespace n1 {
  9     inline void solve() {
 10         double v = vv[1] + sqrt(E / s[1] / k[1]);
 11         printf("%.10f\n", s[1] / v);
 12         return;
 13     }
 14 }
 15
 16 namespace n2 {
 17
 18     inline double cal(double v) {
 19         double ans = s[1] / v;
 20         double delta = k[1] * s[1] * (vv[1] - v) * (vv[1] - v);
 21         double v2 = vv[2] + sqrt((E - delta) / s[2] / k[2]);
 22         if(v2 < 0) return 1e14;
 23         return ans + s[2] / v2;
 24     }
 25
 26     inline void solve() {
 27
 28         double l = 0, r = vv[1] + sqrt(E / s[1] / k[1]);
 29         for(int i = 1; i <= 100; i++) {
 30             double mid = (l + r) / 2;
 31             //printf("l = %.10f r = %.10f \n", l, r);
 32             double ml = mid - (r - l) / 6, mr = mid + (r - l) / 6;
 33             double vl = cal(ml), vr = cal(mr);
 34             if(vl > vr) {
 35                 l = ml;
 36             }
 37             else {
 38                 r = mr;
 39             }
 40         }
 41         printf("%.10f\n", cal(r));
 42         return;
 43     }
 44 }
 45
 46 namespace Fire {
 47     const double eps = 1e-13;
 48     double T = 1000, dT = 0.99999;
 49     double nowE[N], temp[N], lm[N];
 50     int test[N];
 51
 52     inline int rd(int l, int r) {
 53         return rand() % (r - l + 1) + l;
 54     }
 55
 56     inline double Rand() {
 57         return 1.0 * rand() / RAND_MAX;
 58     }
 59
 60     inline double calv(int i, double e) {
 61         return vv[i] + sqrt(e / k[i] / s[i]);
 62     }
 63
 64     inline double calt(int i, double e) {
 65         return s[i] / (vv[i] + sqrt(e / k[i] / s[i]));
 66     }
 67
 68     inline double init() {
 69         for(int i = 1; i <= n; i++) {
 70             if(vv[i] < -eps) {
 71                 lm[i] = k[i] * s[i] * vv[i] * vv[i];
 72                 E -= lm[i];
 73             }
 74         }
 75         double dt = E / n, ans = 0;
 76         for(int i = 1; i <= n; i++) {
 77             nowE[i] = dt;
 78             ans += calt(i, lm[i] + nowE[i]);
 79         }
 80         return ans;
 81     }
 82
 83     inline void solve() {
 84         double ans, fin = 1e14;
 85         srand(2332);
 86         for(int A = 1; A <= 1; A++) {
 87             ans = init();
 88             fin = std::min(ans, fin);
 89             while(T > eps) {
 90                 /// Random a new solution
 91                 int a = rd(1, n), b = rd(1, n);
 92                 while(a == b) {
 93                     a = rd(1, n), b = rd(1, n);
 94                 }
 95                 double deltaE = std::min((long double)nowE[a], (long double)T * 1e11) * Rand();
 96                 temp[a] = nowE[a] - deltaE;
 97                 temp[b] = nowE[b] + deltaE;
 98
 99                 double New = ans - calt(a, lm[a] + nowE[a]) - calt(b, lm[b] + nowE[b])
100                                  + calt(a, lm[a] + temp[a]) + calt(b, lm[b] + temp[b]);
101
102                 fin = std::min(fin, New);
103                 if(New < ans || Rand() < exp((ans - New) / T)) {
104                     ans = New;
105                     nowE[a] = temp[a];
106                     nowE[b] = temp[b];
107                 }
108                 T = T * dT;
109             }
110         }
111         printf("%.8f\n", fin);
112         return;
113     }
114 }
115
116 int main() {
117     scanf("%d%lf", &n, &E);
118     for(int i = 1; i <= n; i++) {
119         scanf("%lf%lf%lf", &s[i], &k[i], &vv[i]);
120     }
121
122     if(n == 1) {
123         n1::solve();
124         return 0;
125     }
126
127     if(n == 2) {
128         n2::solve();
129         return 0;
130     }
131
132     Fire::solve();
133     return 0;
134 }

LOJAC代码

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

转载于:https://www.cnblogs.com/huyufeifei/p/10779552.html

洛谷P2179 骑行川藏相关推荐

  1. [NOI2012]骑行川藏

    [NOI2012]骑行川藏 思路一:二分导数 http://www.cnblogs.com/RabbitHu/p/9019762.html 考虑"性价比"即花费单位能量缩短的时间. ...

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

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

  3. 2876: [Noi2012]骑行川藏

    2876: [Noi2012]骑行川藏 Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special Judge Submit: 1243  Solved: ...

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

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

  5. 牛客每日练习----骑行川藏,Lucky Coins,不凡的夫夫

    大提琴的声音就像一条河,左岸是我无法忘却的回忆,右岸是我值得紧握的璀璨年华,中间流淌的,是我年年岁岁淡淡的感伤. 链接:https://ac.nowcoder.com/acm/problem/1765 ...

  6. BZOJ2876 [Noi2012]骑行川藏

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  7. [BZOJ2876] [NOI2012]骑行川藏

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

  8. bzoj 2876: [Noi2012]骑行川藏 拉格朗日乘子法

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

  9. bzoj 2876: [Noi2012]骑行川藏 二分+拉格朗日乘数法

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

  10. bzoj2876: [Noi2012]骑行川藏 :拉格朗日乘数法

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

最新文章

  1. 计算机如何理解我们的语言?NLP is fun!
  2. IoT半导体购并案效果难现 服务器合作案后来居上
  3. linux删除jpeg动态库,linux如何不用的删除动态库
  4. 【重点!DFS/记忆化递归 + BFS】LeetCode 133. Clone Graph
  5. golang中的那些坑
  6. lazarus中截取整个屏幕画面并保存为指定文件
  7. 第015讲 仿sohu首页面布局
  8. git学习之简介(一)
  9. Android之线性布局的4个重要参数
  10. 怎么禁止使用计算机的软件,电脑如何禁止程序运行 一键彻底禁止电脑软件运行方法...
  11. fw150us的linux驱动下载,FAST FW150US2.0无线网卡驱动
  12. wps根据标题自动生成目录
  13. 禁止每次打开edge自动在开始菜单创建Microsoft Edge 的 Edge 栏
  14. IceSword 1.12
  15. 四旋翼的运动原理及几个飞行问题
  16. 未来科学技十幻想画计算机,人教版美术教案第七册(全册)
  17. 分布式Ruby解决之道 - DRb
  18. linux 导出dump文件
  19. WebRTC回声抵消模块简要分析
  20. 大数据时代下,跨境电商如何利用数据实现快速发展

热门文章

  1. 【第7章】Stable Diffusion WebUI ControlNet基础速成(安装/升级/简介/类别/功能/效果速览)
  2. 计算机网络技术是学什么 1003无标题,哪个计算机网络技术学校最好
  3. 蓝桥杯往年常考算法心得
  4. Rage(PC) Modding Notes
  5. 虚拟主机服务器E,虚拟主机服务器E
  6. [TI TDA4 J721E] 屏幕显示中文字符 生成中文字库—Draw2D 模块应用(UTF-8编码)
  7. Error: 1265, Data truncated for column '列名' at row 1
  8. 4.2黄金走势行情分析-黄金V型反转能否延续涨势?
  9. 金山打字通英文课程带注释_设置打字稿中的类型的演练:注释与推理
  10. 美团商家电话采集软件使用指南