codeforces 489e Hiking dp+01分数规划+二分
来源:互联网 发布:羽绒被缺点 知乎 编辑:程序博客网 时间:2024/05/06 23:41
题意:
一个人在起点0,有n个休息点,每个点有两个数值,分别表示距离起点的距离xi,以及所获得的愉悦值bi
这个人打算每天走L距离,但实际情况不允许他这么做。
定义总体失望值val = sum(sqrt(Ri - L)) / sum(bi); Ri:一天所走的距离。i为所到的节点。
现在要使得val最小(这个人必须要到达最终的节点),让你找出相应的方案,即把所应走的休息点输出。
思路:
一开始用dp,结果是错的,当时也感觉有点不对。
01分数规划,网上找了一下资料以及让铭神解答了一些疑惑,还得多做几题才能熟悉。
对于01分数规划,其实就是求解分数的最值问题。
假如对于原来的式子val = sum(a[i]*x[i])/sum(b[i]*x[i]);//x[i]:1或者0,表示走或不走这个点;
(假设answer就是最优值,放到这题来说,也就是说是最小值;为了方便起见,这里的A、B代表最优的方案)
answer = A/B;
那么对于所有方案有:
answer <= sum(a[i]*x[i])/sum(b[i]*x[i]) ①
移项之后:
sum(a[i]*x[i]) - sum(b[i]*x[i])*answer >= 0 ②
由式子②可看出,最终的answer要使得所有的方案均>=0;
由于现在不知道answer究竟是多少,我们先假设一个值,记为L;
F(L) = sum(a[i]*x[i]) - sum(b[i]*x[i])*L;
可以看出,函数F(L)在方案确定的情况下,L值越大,F(L)值越小,是一个单调递减函数。
但实际上,即使方案不固定,F(L)的值也是随着L的增大而减少。
(图中斜线代表方案,横坐标代表变量L)当L增大的时候,所有的方案F(L)值都会减少。
既然这样,我们就可以二分L来找answer。
二分L,找到使sum(a[i]*x[i])-sum(b[i]*x[i])*L 的最小的方案(对于本题,这个就是用dp实现)
*以下用A[i]表示sum(a[i]*x[i]),B[i]表示sum(b[i]*x[i]);
如果F(L) > 0,则有L < A[i]/B[i](虽说此时的L已经使所有方案均>=0,但此时的L是取不到的。因为A[i]/B[i]已经是当前最小的了,而L却更小)此时应该把下界上移,即l = mid;
如果F(L)< 0,则有L > A[i]/B[i],说明L太大,其实可以再小一点。因为A[i]/B[i]就是更优的方案。此时应该把上界下移,即r = mid;
类似的,如果是求最大值,则只要把式子①改为”>=“。
*由于也才刚学的01分数规划,本想说得更通用点,限于目前的理解,只能到这里。如果上文有哪里不对的话,还望指正。
code:
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int MAXN = 1e3+5;const int INF = 0x3f3f3f3f;int n, l;int x[MAXN], b[MAXN];int par[MAXN];double dp[MAXN];void getRoute(int i){ if(i == 0) return; getRoute(par[i]); cout<<i<<" ";}bool check(double L){ dp[0] = 0; for(int i = 1;i <= n; i++) { dp[i] = INF; for(int j = 0;j < i ;j++) { double tmp = dp[j] + sqrt(1.0 * abs(x[i]-x[j]-l)) - L*b[i]; if(tmp < dp[i]) { dp[i] = tmp; par[i] = j; } } } if(dp[n] < 0) return true; return false;} void solve(){ double l = 0, r = 1e10; while(r-l > 1e-8) { double mid = (l+r)/2; if(check(mid)) r = mid; else l = mid; } getRoute(n); cout<<endl;} int main(){ ios::sync_with_stdio(false); cin>>n>>l; for(int i = 1;i <= n ;i++) cin>>x[i]>>b[i]; solve(); return 0;}
- codeforces 489e Hiking dp+01分数规划+二分
- codeforces 277.5 E.Hiking 01分数规划
- Codeforces 489E Hiking(普通01分数规划加DP)
- Codeforces Round #277.5(Div. 2)E. Hiking【Dp+01分数规划】
- Codeforces Round #277.5 (Div. 2) E. Hiking(二分 DP)
- 【Codeforces】 489E Hiking
- CodeForces 489E Hiking
- Codeforces 489E Hiking
- CodeForces 489E Hiking
- Codeforce 489E(dp+01分数规划)
- 01分数规划+二分搜索
- POJ2976(01分数规划+二分)
- Codeforces 743E(二分+状压dp)
- poj 2976(01分数规划+二分)
- POJ-2976-01分数规划,二分
- POJ2976-01分数规划&二分-Dropping tests
- codeforces 710E Generate a String [dp]【动态规划】
- poj 2976 Dropping tests(01分数规划+二分)
- 解决MyEclipse的Unable to update index for central|http://repo1.maven.org/maven2问题
- Android中sql数据库代码学习一
- 考研和工作的建议
- 读写锁实现
- 调试NS2, 使用Eclipse CDT或Qt Creator ------ NS2学习日记 (1)
- codeforces 489e Hiking dp+01分数规划+二分
- vs2012运行c语言出现:无法查找或打开 PDB 文件
- highcharts之pie3D
- [QT4.8 学习手记] QT 4.8 安装
- 声卡其实是一个很好的模数转换设备
- 解析Java中静态变量与实例变量的区别
- div+css小技巧(持续更新中)
- 从Linux内核镜像中提取内核配置文件
- centos中文输入法设定