UVA 10767-Barcelona’s trams(DP+数学推导)

题目大意:有一个列车,要走n个路段,每个路段有一定的长度。初始时,最大速度是M,每次在一个路段要开始的时候,司机可以选择一个速度,在(0,M]之间的任意值v。则发生冲突的概率是v/M,如果发生冲突,那么将会需要10秒恢复并且以恒定的速度5运行到这个路段完毕。并且如果发生冲突,M的值会少1(这样会对后面的路段有影响)。求运行完所有路段的最小花费时间。如果发生冲突,那么假设冲突在中点发生。还有些细节参考原题。。

逆序递推,用d[i][j]表示在第i个路段开始之前,M被减少了j次(即此时最大速度为M-j)的时候,最大的速度。

假设此时速度取x时,能得到时间的最小值。用s表示第i段的长度。可以得出:

d[i][j]=x/M*(s/2x+s/10+d[i+1][j+1]+10)+(1-x/M)*(s/x+d[i+1][j])

将这个式子化简可以得到:

d[i][j]=x*(s/10M+d[i+1][j+1]/M+10/M-d[i+1][j]/M)+s*(1/x)+d[i+1][j]-s/2M

问题很明了了,要么是单调递减函数,要么是双钩函数。双钩函数时需要判断最值是否能取到。

求出最小值完成递推。

偶然遇到了这题。。怀念高中的岁月。。

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
double a[30];
double d[30][30];
int main(void)
{
	int i,j,n;
	double u,v,p,m,M;
	while(scanf("%lf%d",&m,&n)==2)
	{
		for(i=1;i<=n;i++)
		{
			scanf("%lf",&a[i]);
		}
		for(j=n+1;j>=0;j--)
		{
			d[n+1][j]=0;
		}
		for(i=n;i>=1;i--)
		{
			for(j=i-1;j>=0;j--)
			{
				M=m-j;
				u=(a[i]/10+d[i+1][j+1]+10-d[i+1][j])/M;
				v=a[i];
				p=d[i+1][j]-a[i]/(2*M);
				if((u<1e-10)||(sqrt(v/u)-M>1e-10))
				{
					d[i][j]=M*u+v/M+p;
				}
				else
				{
					d[i][j]=2*sqrt(u*v)+p;
				}
			}
		}
		printf("%.4f\n",d[1][0]);
	}
	return 0;
}
时间: 2024-11-04 19:05:10

UVA 10767-Barcelona’s trams(DP+数学推导)的相关文章

leetcode 343. Integer Break(dp或数学推导)

Given a positive integer n, break it into the sum of at least two positive integers and maximize the product of those integers. Return the maximum product you can get. For example, given n = 2, return 1 (2 = 1 + 1); given n = 10, return 36 (10 = 3 +

Codeforces Round #360 (Div. 2) D 数学推导 E dp

Codeforces Round #360 (Div. 2) A  == B  水,但记一下: 第 n 个长度为偶数的回文数是  n+reverse(n). C    dfs 01染色,水 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i

hdu-5000 Clone(DP+数学)

该题是一道需要先进行数学推导的dp题 , 可惜我没有学过离散数学,现在也不是很明白 .   大致的意思是说按照题目中的要求,所有能存活下来的克隆人(一个向量,有很多属性)构成了一条最长反链,具有偏序关系 .偏序关系说白了就是对于向量a.b,不能确定他俩的大小关系 .   那么什么是反链呢?  其实也是不可比的意思,只不过每次将某个属性加减1,可以组成一条最长反链 ,如下图: 对于每一行,构成了一条反链 ,那么最长的就是结点最多的那一行 . 代码如下: 版权声明:本文为博主原创文章,未经博主允许不

hdu-5621 KK&#39;s Point(dp+数学)

题目链接: KK's Point Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Others) Problem Description Our lovely KK has a difficult mathematical problem:He points N(2≤N≤10^5) points on a circle,there are all different.Now he's goi

uva 12186 Another Crisis 树形dp

// uva 12186 Another Crisis 树形dp // // 对于一个节点u,有k个子节点,则至少有c = (k * T - 1) / 100 + 1才能 // 发信,即c / k >= T / 100,则 c 的值为 k * T /100,上取整变成上式 // 将所有的子节点d从小到大排序,取前c个就是d[u]的值 // 紫书上的一题,之前看了好久好久,觉得挺好的,然而一直没做,今天就来 // 体验体验,挺好的一题,注意一下,如果一个节点是叶节点,直接return 1就好 //

UVA 1399 - Puzzle(AC自动机+DP)

UVA 1399 - Puzzle 题目链接 题意:给定一些字符串,求一个最长的不在包含这些子串的字符串,如果可以无限长输出No 思路:建ACM自动机,把不可走结点标记构造出来,然后在这个状态图上进行dp找出最长路径即可,至于无限长的情况,只要在dp前进行一次dfs判有没有环即可 代码: #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include &

UVA 1558 - Number Game(博弈dp)

UVA 1558 - Number Game 题目链接 题意:20之内的数字,每次可以选一个数字,然后它的倍数,还有其他已选数的倍数组合的数都不能再选,谁先不能选数谁就输了,问赢的方法 思路:利用dp记忆化去求解,要输出方案就枚举第一步即可,状态转移过程中,选中一个数字,相应的变化写成一个函数,然后就是普通的博弈问题了,必胜态之后必有必败态,必败态之后全是必胜态 代码: #include <stdio.h> #include <string.h> const int N = 105

uva 417 - Word Index(数位dp)

题目连接:uva 417 - Word Index 题目大意:按照题目中的要求,为字符串编号,现在给出字符串,问说编号为多少,注意字符串必须为递增的,否则编号为0. 解题思路:其实就是算说比给定字符串小并且满足递增的串由多少个.dp[i][j]表示第i个位为j满足比给定字符串小并且满足递增的串. dp[i][j]=∑k=0j?1dp[i?1][k]. 注意每次要处理边界的情况,并且最后要加上自身串.并且在处理边界的时候dp[i][0]要被赋值为1,代表前i个为空的情况. #include <cs

UVA 10641 - Barisal Stadium(DP + 几何)

题目链接:10641 - Barisal Stadium 题意:逆时针给定n个点,在给m个灯,每个灯有一个花费,要求最小花费使得所有边能被灯照到 思路:用向量叉积判断向量的顺逆时针关系,从而预处理出每个灯能照到的边,然后由于n个点是环的,所以可以直接扩大两倍,dp时候去枚举起点即可 状态为dp[i]表示现在照到i条边之前的边全部照亮需要的最小花费 代码: #include <stdio.h> #include <string.h> const double eps = 1e-6;