Bzoj3352 [ioi2009]旅行商
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 89 Solved: 36
Description
Input
Output
Sample Input
2 80 100
20 125 130
10 75 150
5 120 110
Sample Output
HINT
Source
动态规划 线性dp 线段树优化
设 $f[i][j]$ 表示第 i 天停在j号展会位置时的最大收益。
显然有 $ f[i][j] = max{f[i-1][k] * cost(k,j)}+ w[j] $
注意到天数和展会数同级,可以认为多数展会不在同一天,这时可以把第一维i丢掉。
丢掉以后空间够了,时间复杂度还是太高啊?
我们把cost展开,当顺流而下的时候,假设向i转移的时候,j位置比k位置优,有:
$$ f[j] - (L_i-L_j) * D > f[k] - (L_i-L_k) * D $$
$$ f[j]+L_j*D > f[k] + L_k*D $$
把$ f[j]+L_j*D $ 丢进线段树里,维护区间最大值即可$O(logn)$查询。
逆流而上同理。
当一些展会挤在同一天的时候怎么处理?
撕烤一下可以发现同一天经过的展会一定是一个连续的区间(从一点到另一点的时候如果中途经过别的展会,不拿白不拿)。
对于每一个终点,分类讨论起点在上游还是下游,枚举起点找最大收益,这样显然是正确的。
维护two-pointers或者前缀最大值即可快速转移。
78行的初始化边界没有加,WA*2
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int INF=0x3f3f3f3f;
const int mxn=;
int read(){
int x=,f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,m,D,U,S;
struct met{
int day,x;
int w;
bool operator < (const met &b)const{
return (day==b.day && x<b.x) || day<b.day;
}
}a[mxn];
int f[mxn];
int tmp[mxn],tmp2[mxn];
//
struct node{
int mxu,mxd;
}t[mxn<<];
#define ls rt<<1
#define rs rt<<1|1
inline void pushup(int rt){
t[rt].mxd=max(t[ls].mxd,t[rs].mxd);
t[rt].mxu=max(t[ls].mxu,t[rs].mxu);
return;
}
void Build(int l,int r,int rt){
if(l==r){t[rt].mxd=t[rt].mxu=-INF;return;}
int mid=(l+r)>>;
Build(l,mid,ls);Build(mid+,r,rs);
pushup(rt);
return;
}
void update(int p,int l,int r,int rt){
if(l==r){
t[rt].mxd=f[p]+a[p].x*D; t[rt].mxu=f[p]-a[p].x*U;
return;
}
int mid=(l+r)>>;
if(a[p].x<=mid)update(p,l,mid,ls);
else update(p,mid+,r,rs);
pushup(rt);
return;
}
//
int MXU,MXD;
void query(int L,int R,int l,int r,int rt){
if(L<=l && r<=R){
MXD=max(t[rt].mxd,MXD);MXU=max(t[rt].mxu,MXU);
return;
}
int mid=(l+r)>>;
if(L<=mid)query(L,R,l,mid,ls);
if(R>mid)query(L,R,mid+,r,rs);
return;
}
void solve(){
Build(,m,);
update(,,m,);
for(int i=,j;i<=n;i=j+){
for(j=i;a[j].day==a[i].day;j++){
f[j]=-INF;
MXU=-INF; query(a[j].x,m,,m,);
f[j]=max(f[j],MXU+a[j].x*U);
MXD=-INF; query(,a[j].x,,m,);
f[j]=max(f[j],MXD-a[j].x*D);
f[j]+=a[j].w;
}j--;
tmp[i]=f[i];tmp2[j]=f[j];
for(int k=i+;k<=j;k++)
tmp[k]=max(f[k],tmp[k-]-(a[k].x-a[k-].x)*D+a[k].w);
for(int k=j-;k>=i;k--)
tmp2[k]=max(f[k],tmp2[k+]-(a[k+].x-a[k].x)*U+a[k].w);
for(int k=i;k<=j;k++){
f[k]=max(f[k],max(tmp[k],tmp2[k]));
update(k,,m,);
}
}
printf("%d\n",f[n]);
return;
}
int main(){
int i,j;
n=read();
U=read();D=read();
S=read();
a[]=(met){,S,};n++;
for(i=;i<=n;i++){
a[i].day=read();a[i].x=read();a[i].w=read();
m=max(m,a[i].x);
}
sort(a+,a+n+);++n;
a[n]=(met){a[n-].day+,S,};
m=max(m,S);
solve();
return ;
}
Bzoj3352 [ioi2009]旅行商的更多相关文章
- 【C#代码实战】群蚁算法理论与实践全攻略——旅行商等路径优化问题的新方法
若干年前读研的时候,学院有一个教授,专门做群蚁算法的,很厉害,偶尔了解了一点点.感觉也是生物智能的一个体现,和遗传算法.神经网络有异曲同工之妙.只不过当时没有实际需求学习,所以没去研究.最近有一个这样 ...
- 洛谷P1782 旅行商的背包[多重背包]
题目描述 小S坚信任何问题都可以在多项式时间内解决,于是他准备亲自去当一回旅行商.在出发之前,他购进了一些物品.这些物品共有n种,第i种体积为Vi,价值为Wi,共有Di件.他的背包体积是C.怎样装才能 ...
- 2016全国研究生数学建模A题多无人机协同任务规划——基于分布式协同多旅行商MTSP遗传算法
MTSP问题是指:有Ⅳ个城市,要求旅行商到达每个城市各一次,且仅一次,并[旦 1到起点,且要求旅行路线最短.而多旅行商问题M个旅行商从同一个城市(或多个城市)出发.分羽走一条旅路线,且总路程缀短.有关 ...
- [vijos P1014] 旅行商简化版
昨天早上上课讲旅行商问题,有点难,这周抽空把3^n的算法码码看.不过这个简化版已经够折腾人了. 其一不看解析不知道这是双进程动态规划,不过我看的解析停留在f[i,j]表示第一个人走到i.第二个人走到j ...
- vijosP1014 旅行商简化版
vijosP1014 旅行商简化版 链接:https://vijos.org/p/1014 [思路] 双线DP. 设ab,ab同时走.用d[i][j]表示ab所处结点i.j,且定义i>j,则有转 ...
- 洛谷【P1523】旅行商的背包(算法导论 15-1) 题解
P1523 旅行商简化版 题目背景 欧几里德旅行商\((Euclidean Traveling Salesman)\)问题也就是货郎担问题一直是困扰全世界数学家.计算机学家的著名问题.现有的算法都没有 ...
- hdu 4281 Judges' response(多旅行商&DP)
Judges' response Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- 旅行商(sale)
旅行商(sale) 题目描述 camp国有n座城市,由1,2,-,n编号.城市由n–1条双向道路相连.任意两个城市之间存在唯一的道路连通.有m个旅行商,第i个旅行商会从城市ai旅行到城市bi,贩卖ci ...
- 洛谷P1523 旅行商简化版(DP)
题目: P1523 旅行商简化版 解析 可以看做是两个人同时从西往东走,经过不一样的点,走到最东头的方案数 设\(f[i][j]\)表示一个人走到i,一个人走到j的最短距离(\(i<j\)) 第 ...
随机推荐
- 30行js让你的rem弹性布局适配所有分辨率(含竖屏适配)(转载)
用rem来实现移动端的弹性布局是个好主意!用法如下: CSS @media only screen and (max-width: 320px), only screen and (max-devic ...
- Sql Server中判断表、列不存在则创建的方法[转]
一.Sql Server中如何判断表中某列是否存在 首先跟大家分享Sql Server中判断表中某列是否存在的两个方法,方法示例如下: 比如说要判断表A中的字段C是否存在两个方法: 第一种方法 ? ...
- vue 组件 模板input双向数据数据
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>T ...
- es6 const关键字
const是constant(常量)的缩写,const和 let一样,也是用来声明变量的,但是const是专门用于声明一个常量的,顾名思义,常量的值是不可改变的.以前用var声明的变量,想怎么改就怎么 ...
- mysql 添加行号
首先准备演示数 DROP TABLE IF EXISTS `computer_stu`; CREATE TABLE `computer_stu` ( `id` ) NOT NULL, `name` ) ...
- [洛谷P4819][中山市选]杀人游戏
题目大意:有一张$n$个点$m$条边的有向图,有一个关键点,如果你访问一个点,你会知道它连出的边中有没有关键点,以及若有的话是哪个.问最优策略下不访问关键点而知道关键点的概率 题解:发现若一个点不是关 ...
- 【Cf #503 B】The hat(二分)
为什么Cf上所有的交互题都是$binary \; Search$... 把序列分成前后两个相等的部分,每一个都可以看成一条斜率为正负$1$的折线.我们把他们放在一起,显然,当折线的交点的横坐标为整数时 ...
- Mac OS 装gdb
1 要求按照mac ports 2 命令:sudo port install gdb 3 安装位置在: /opt/local/bin/ggdb , 注意,ggdb是执行命令
- 笛卡尔树Cartesian Tree
前言 最近做题目,已经不止一次用到笛卡尔树了.这种数据结构极为优秀,但是构造的细节很容易出错.因此写一篇文章做一个总结. 笛卡尔树 Cartesian Tree 引入问题 有N条的长条状的矩形,宽度都 ...
- POJ 1966 Cable TV Network 【经典最小割问题】
Description n个点的无向图,问最少删掉几个点,使得图不连通 n<=50 m也许可以到完全图? Solution 最少,割点,不连通,可以想到最小割. 发现,图不连通,必然存在两个点不 ...