CSU 1806 Toll
2016-09-05 19:52
246 查看
Description
In ICPCCamp, there are n cities and m unidirectional roads between cities. The i-th road goes from the ai-th cityto the bi-th city. For each pair of cities u and v, there is at most one road from u to v.
As traffic in ICPCCamp is becoming heavier, toll of the roads also varies. At time t, one should pay (ci⋅t+di)
dollars to travel along the i-th road.
Bobo living in the 1-st city would like to go to the n-th city. He wants to know the average money he must spend at least if he starts from city 1 at t∈[0,T]. Note that since Bobo's car is super-fast, traveling on the roads costs him no
time.
Formally, if f(t) is the minimum money he should pay from city 1 to city n at time t, Bobo would like to find
Input
The first line contains 3 integers n,m,T (2≤n≤10,1≤m≤n(n-1),1≤T≤104).The i-th of the following m lines contains 4 integers ai,bi,ci,di (1≤ai,bi≤n,ai≠bi,0≤ci,di≤103).
It is guaranteed that Bobo is able to drive from city 1 to city n.
Output
A floating number denotes the answer. It will be considered correct if its absolute or relative error does not exceed 10-6.
Sample Input
3 3 2 1 2 1 0 2 3 1 0 1 3 1 1 3 3 2 1 2 1 0 2 3 1 0 1 3 0 5
Sample Output
1.750000002.00000000
有一个积分公式,看似很难的题。
稍微分析一下,其实可以发现,因为c和d是非负整数,显然,从1到n的花费只会随时间增加而增加。
并且,可以发现,对于同一时间,我们会优先选择通过路上∑ci较小的路,因为∑di是不会随时间变动的。
于是,可以以∑ci分段,对于同一段里,∑ci和∑di一定是相同的,
这一段的积分就是(r-l)*((r+l)/2)*∑ci+∑di),最后加起来除于t即可。
#include<set>
#include<map>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<bitset>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define rep(i,j,k) for (int i = j; i <= k; i++)
#define per(i,j,k) for (int i = j; i >= k; i--)
#define loop(i,j,k) for (int i = j;i != -1; i = k[i])
#define lson x << 1, l, mid
#define rson x << 1 | 1, mid + 1, r
#define ff first
#define ss second
#define mp(i,j) make_pair(i,j)
#define pb push_back
#define pii pair<int,int>
#define in(x) scanf("%d", &x);
using namespace std;
typedef long long LL;
const int low(int x) { return x&-x; }
const double eps = 1e-8;
const int INF = 0x7FFFFFFF;
const int mod = 1e9 + 7;
const int N = 15;
int n, m, t, x, y;
int c
, d
;
double dis
;
int u
, v
, vis
;
pii check(double t)
{
rep(i, 1, n) dis[i] = -1, u[i] = v[i] = vis[i] = 0;
dis[1] = 0;
while (true)
{
x = 0;
rep(i, 1, n)
{
if (dis[i] < 0 || vis[i]) continue;
if (!x || dis[i] < dis[x]) x = i;
}
if (!x) break; vis[x] = 1;
rep(i, 1, n)
{
if (c[x][i] == -1) continue;
if (dis[i]<0 || dis[i] - eps > dis[x] + t*c[x][i] + d[x][i])
{
dis[i] = dis[x] + t*c[x][i] + d[x][i];
u[i] = u[x] + c[x][i];
v[i] = v[x] + d[x][i];
}
else if (fabs(dis[x] + t*c[x][i] + d[x][i] - dis[i]) < eps)
{
if (u[i] > u[x] + c[x][i])
{
u[i] = u[x] + c[x][i];
v[i] = v[x] + d[x][i];
}
}
}
}
return mp(u
, v
);
}
int main()
{
while (scanf("%d%d%d", &n, &m, &t) != EOF)
{
memset(c, -1, sizeof(c));
while (m--)
{
scanf("%d%d", &x, &y);
scanf("%d%d", &c[x][y], &d[x][y]);
}
double l = 0, r = t, ans = 0;
pii bef = check(l);
while (l + eps < r)
{
double q = l, h = r;
pii now;
while (q + eps < h)
{
now = check((q + h) / 2);
if (now.ff == bef.ff) q = (q + h) / 2;
else h = (q + h) / 2;
}
ans += (h - l) * ((h + l) / 2 * bef.ff + bef.ss);
bef = check(l = h);
}
printf("%.8lf\n", ans / t);
}
return 0;
}
去翻了翻网上的题解,看到的全是simpson求积分,吓得我赶紧去学了一发,原来还有这么好用的东西。
#include<set> #include<map> #include<ctime> #include<cmath> #include<stack> #include<queue> #include<bitset> #include<cstdio> #include<string> #include<cstring> #include<iostream> #include<algorithm> #include<functional> #define rep(i,j,k) for (int i = j; i <= k; i++) #define per(i,j,k) for (int i = j; i >= k; i--) #define loop(i,j,k) for (int i = j;i != -1; i = k[i]) #define lson x << 1, l, mid #define rson x << 1 | 1, mid + 1, r #define ff first #define ss second #define mp(i,j) make_pair(i,j) #define pb push_back #define pii pair<int,int> #define in(x) scanf("%d", &x); using namespace std; typedef long long LL; const int low(int x) { return x&-x; } const double eps = 1e-8; const int INF = 0x7FFFFFFF; const int mod = 1e9 + 7; const int N = 15; int n, m, t, x, y; int c , d ; double dis ; int vis ; double get(double t) { rep(i, 1, n) dis[i] = -1, vis[i] = 0; dis[1] = 0; while (true) { x = 0; rep(i, 1, n) { if (dis[i] < 0 || vis[i]) continue; if (!x || dis[i] < dis[x]) x = i; } if (!x) break; vis[x] = 1; rep(i, 1, n) { if (c[x][i] == -1) continue; if (dis[i] > eps && dis[i] + eps < dis[x] + t*c[x][i] + d[x][i]) continue; dis[i] = dis[x] + t * c[x][i] + d[x][i]; } } return dis ; } double simpson(double l, double r) { return (r - l) / 6 * (get(l) + 4 * get((l + r) / 2) + get(r)); } double solve(double l, double r) { double mid = (l + r) / 2, now = simpson(l, r); if (fabs(simpson(l, mid) + simpson(mid, r) - now) < eps) return now; return solve(l, mid) + solve(mid, r); } int main() { while (scanf("%d%d%d", &n, &m, &t) != EOF) { memset(c, -1, sizeof(c)); while (m--) { scanf("%d%d", &x, &y); scanf("%d%d", &c[x][y], &d[x][y]); } printf("%.8lf\n", solve(0, t) / t); } return 0; }
相关文章推荐
- Cpp环境【CQYZOJ1496】【Code[VS]5287】搬家大冒险
- 347. Top K Frequent Elements
- C/C++框架
- C/C++框架
- UVa 489,紫书P79,刽子手游戏
- http://www.importnew.com/20307.html
- 计数排序(COUNTING-SORTING)
- 一些快捷键。【会不断补充..】
- word2vec使用指导
- UVA - 10341 Solve It (数学--二分法求解)
- 第二周项目0宣告主权
- 启动模式:singleTask 不是 Intent.FLAG_ACTIVITY_NEW_TASK!
- 让洪水猛兽变成温顺小羊——浅谈Android线程池机制
- 26. Remove Duplicates from Sorted Array
- fullpage.js全屏滚动插件使用小结
- C#枚举描述获取
- 【JZOJ 3052】剪草
- 计算机网络入门概念理解
- 关于面试时项目的介绍
- python并行任务之生产消费模式