BZOJ4200 & 洛谷2304 & UOJ132:[NOI2015]小园丁与老司机——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4200
https://www.luogu.org/problemnew/show/P2304
小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面。田野上有 nn 棵许愿树,编号 1,2,3,…,n1,2,3,…,n,每棵树可以看作平面上的一个点,其中第 ii 棵树 (1≤i≤n1≤i≤n) 位于坐标 (xi,yi)(xi,yi)。任意两棵树的坐标均不相同。老司机 Mr. P 从原点 (0,0)(0,0) 驾车出发,进行若干轮行动。每一轮,Mr. P 首先选择任意一个满足以下条件的方向:为左、右、上、左上 45∘45∘ 、右上 45∘45∘ 五个方向之一。沿此方向前进可以到达一棵他尚未许愿过的树。完成选择后,Mr. P 沿该方向直线前进,必须到达该方向上距离最近的尚未许愿的树,在树下许愿并继续下一轮行动。如果没有满足条件的方向可供选择,则停止行动。他会采取最优策略,在尽可能多的树下许愿。若最优策略不唯一,可以选择任意一种。不幸的是,小园丁 Mr. S 发现由于田野土质松软,老司机 Mr. P 的小汽车在每轮行进过程中,都会在田野上留下一条车辙印,一条车辙印可看作以两棵树(或原点和一棵树)为端点的一条线段。在 Mr. P 之后,还有很多许愿者计划驾车来田野许愿,这些许愿者都会像 Mr. P 一样任选一种最优策略行动。Mr. S 认为非左右方向(即上、左上 45∘45∘ 、右上 45∘45∘ 三个方向)的车辙印很不美观,为了维护田野的形象,他打算租用一些轧路机,在这群许愿者到来之前夯实所有“可能留下非左右方向车辙印”的地面。“可能留下非左右方向车辙印”的地面应当是田野上的若干条线段,其中每条线段都包含在某一种最优策略的行进路线中。每台轧路机都采取满足以下三个条件的工作模式:从原点或任意一棵树出发。只能向上、左上 45∘45∘ 、右上 45∘45∘ 三个方向之一移动,并且只能在树下改变方向或停止。只能经过“可能留下非左右方向车辙印”的地面,但是同一块地面可以被多台轧路机经过。现在 Mr. P 和 Mr. S 分别向你提出了一个问题:请给 Mr .P 指出任意一条最优路线。请告诉 Mr. S 最少需要租用多少台轧路机。
哈哈哈我可能是疯了所以才去做了码农题,然后dp不会最小流写跪哈哈哈
直接看这个吧,心累到懒得讲题解了:https://blog.csdn.net/litble/article/details/80463466
另外开O2的时候普通的最小流也可以通过,不开的时候就会奇妙RE。
(自认码风不错)
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int INF=1e9;
const int N=5e4+;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct point{
int x,y,b1,b2,id;
}p[N];
int n,b[N],c[N],d[N],e[N],l1,l2,l3,l4;
int to[][N],lft[N],straight[N],rigt[N];
int f[N],g[N],flor[N],num[N];
vector<int>ty[N];
inline bool cmpx(point a,point b){
return a.x<b.x;
}
inline bool cmpy(point a,point b){
return a.y>b.y;
}
void LSH(){
sort(b+,b+l1+);sort(c+,c+l2+);
sort(d+,d+l3+);sort(e+,e+l4+);
l1=unique(b+,b+l1+)-b-,l2=unique(c+,c+l2+)-c-;
l3=unique(d+,d+l3+)-d-,l4=unique(e+,e+l4+)-e-;
for(int i=;i<=n;i++){
p[i].x=lower_bound(b+,b+l1+,p[i].x)-b;
p[i].y=lower_bound(c+,c+l2+,p[i].y)-c;
p[i].b1=lower_bound(d+,d+l3+,p[i].b1)-d;
p[i].b2=lower_bound(e+,e+l4+,p[i].b2)-e;
}
}
void init(){
LSH();
sort(p+,p+n+,cmpy);
for(int i=;i<=n;i++){
int id=p[i].id;
to[][id]=lft[p[i].b2];
to[][id]=straight[p[i].x];
to[][id]=rigt[p[i].b1];
lft[p[i].b2]=id;
straight[p[i].x]=id;
rigt[p[i].b1]=id;
}
sort(p+,p+n+,cmpx);
for(int i=;i<=n;i++){
ty[p[i].y].push_back(p[i].id);
flor[p[i].id]=p[i].y;
num[p[i].id]=ty[p[i].y].size()-;
}
}
int pre[N],lrs[N];
void output(int id){
if(id!=lrs[id]){
int fll=flor[id];
if(num[id]<num[lrs[id]]){
for(int i=num[id]-;i>=;i--)printf("%d ",ty[fll][i]);
for(int i=num[id]+;i<=num[lrs[id]];i++)printf("%d ",ty[fll][i]);
}else{
int sz=ty[fll].size();
for(int i=num[id]+;i<sz;i++)printf("%d ",ty[fll][i]);
for(int i=num[id]-;i>=num[lrs[id]];i--)printf("%d ",ty[fll][i]);
}
}
id=lrs[id];
if(pre[id]){
printf("%d ",pre[id]);
output(pre[id]);
}
}
void work1(){
init();
for(int i=l2;i>=;i--){
int maxn=,id=,sz=ty[i].size();
for(int j=;j<sz;j++){//处理直行和向右再左走
int I=ty[i][j];
int J1=to[][I],J2=to[][I],J3=to[][I];
if(J1&&g[I]<f[J1])g[I]=f[J1],pre[I]=J1;
if(J2&&g[I]<f[J2])g[I]=f[J2],pre[I]=J2;
if(J3&&g[I]<f[J3])g[I]=f[J3],pre[I]=J3;
if(maxn>g[I]+)f[I]=maxn,lrs[I]=id;
else f[I]=g[I]+,lrs[I]=I;
if(sz-j+g[I]>maxn)maxn=sz-j+g[I],id=I;
}
maxn=id=;
for(int j=sz-;j>=;j--){//处理向左再右走
int I=ty[i][j];
if(maxn>f[I])f[I]=maxn,lrs[I]=id;
if(g[I]+j+>maxn)maxn=g[I]+j+,id=I;
}
}
printf("%d\n",f[n]-);output(n);puts("");
}
struct node{
int to,nxt,w;
}edge[N*];
int cnt,head[N],S,T,du[N];
int cur[N],lev[N],dui[N];
bool ok[N];
inline void adde(int u,int v,int w){
edge[++cnt].to=v;edge[cnt].w=w;edge[cnt].nxt=head[u];head[u]=cnt;
edge[++cnt].to=u;edge[cnt].w=;edge[cnt].nxt=head[v];head[v]=cnt;
}
inline void add(int u,int v){
for(int i=head[u];i!=-;i=edge[i].nxt)
if(edge[i].to==v)return;
du[u]--;du[v]++;adde(u,v,INF-);
}
bool bfs(int m){
int r;
for(int i=;i<=m;i++){
cur[i]=head[i];lev[i]=-;
}
dui[r=]=S;lev[S]=;
for(int i=;i<=r;i++){
int u=dui[i];
for(int j=head[u];j!=-;j=edge[j].nxt){
int v=edge[j].to,w=edge[j].w;
if(lev[v]==-&&w){
lev[v]=lev[u]+;
dui[++r]=v;
if(v==T)return ;
}
}
}
return ;
}
int dinic(int u,int flow,int m){
if(u==m)return flow;
int res=,delta;
for(int &i=cur[u];i!=-;i=edge[i].nxt){
int v=edge[i].to;
if(lev[v]>lev[u]&&edge[i].w){
delta=dinic(v,min(flow,edge[i].w),m);
if(delta){
edge[i].w-=delta;
edge[i^].w+=delta;
res+=delta;
if(res==flow)break;
}
}
}
if(res!=flow)lev[u]=-;
return res;
}
void build(){
ok[n]=;
for(int i=;i<=l2;i++){
int sz=ty[i].size();
for(int j=;j<sz;j++){
int I=ty[i][j];
if(!ok[I])continue;
for(int k=;k<j;k++){
int J=ty[i][k];
int K1=to[][J],K2=to[][J],K3=to[][J];
if(K1&&f[K1]+sz-k==f[I])add(J,K1),ok[K1]=;
if(K2&&f[K2]+sz-k==f[I])add(J,K2),ok[K2]=;
if(K3&&f[K3]+sz-k==f[I])add(J,K3),ok[K3]=;
}
for(int k=j+;k<sz;k++){
int J=ty[i][k];
int K1=to[][J],K2=to[][J],K3=to[][J];
if(K1&&f[K1]+k+==f[I])add(J,K1),ok[K1]=;
if(K2&&f[K2]+k+==f[I])add(J,K2),ok[K2]=;
if(K3&&f[K3]+k+==f[I])add(J,K3),ok[K3]=;
}
int K1=to[][I],K2=to[][I],K3=to[][I];
if(K1&&f[K1]+==f[I])add(I,K1),ok[K1]=;
if(K2&&f[K2]+==f[I])add(I,K2),ok[K2]=;
if(K3&&f[K3]+==f[I])add(I,K3),ok[K3]=;
}
}
}
void work2(){
memset(head,-,sizeof(head));cnt=-;
build();
S=n+,T=S+;
int ans=;
for(int i=;i<=n;i++){
if(du[i]>)adde(S,i,du[i]),ans+=du[i];
else if(du[i]<)adde(i,T,-du[i]);
}
while(bfs(T))ans-=dinic(S,INF,T);
printf("%d\n",ans);
}
int main(){
n=read();
for(int i=;i<=n;i++){
p[i].x=b[++l1]=read();
p[i].y=c[++l2]=read();
p[i].b1=d[++l3]=p[i].y-p[i].x;
p[i].b2=e[++l4]=p[i].y+p[i].x;
p[i].id=i;
}
p[++n].x=b[++l1]=;
p[n].y=c[++l2]=;
p[n].b1=d[++l3]=;
p[n].b2=e[++l4]=;
p[n].id=n;
work1();work2();
return ;
}
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++
BZOJ4200 & 洛谷2304 & UOJ132:[NOI2015]小园丁与老司机——题解的更多相关文章
- 【洛谷2304_LOJ2134】[NOI2015]小园丁与老司机(动态规划_网络流)
题目: 洛谷 2304 LOJ 2134 (LOJ 上每个测试点有部分分) 写了快一天 -- 好菜啊 分析: 毒瘤二合一题 -- 注意本题(及本文)使用 \(x\) 向右,\(y\) 向上的「数学坐标 ...
- [UOJ#132][BZOJ4200][luogu_P2304][NOI2015]小园丁与老司机
[UOJ#132][BZOJ4200][luogu_P2304][NOI2015]小园丁与老司机 试题描述 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面.田野上有 \(n\) 棵许愿 ...
- [BZOJ4200][Noi2015]小园丁与老司机
4200: [Noi2015]小园丁与老司机 Time Limit: 20 Sec Memory Limit: 512 MBSec Special JudgeSubmit: 106 Solved ...
- 【BZOJ4200】[Noi2015]小园丁与老司机 DP+最小流
[BZOJ2839][Noi2015]小园丁与老司机 Description 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面.田野上有 nn 棵许愿树,编号 1,2,3,…,n1,2, ...
- luogu P2304 [NOI2015]小园丁与老司机 dp 上下界网络流
LINK:小园丁与老司机 苦心人 天不负 卧薪尝胆 三千越甲可吞吴 AC的刹那 真的是泪目啊 很久以前就写了 当时记得特别清楚 写到肚子疼.. 调到胳膊疼.. ex到根不不想看的程度. 当时wa了 一 ...
- uoj132/BZOJ4200/洛谷P2304 [Noi2015]小园丁与老司机 【dp + 带上下界网络流】
题目链接 uoj132 题解 真是一道大码题,,,肝了一个上午 老司机的部分是一个\(dp\),观察点是按\(y\)分层的,而且按每层点的上限来看可以使用\(O(nd)\)的\(dp\),其中\(d\ ...
- 【bzoj4200】[Noi2015]小园丁与老司机 STL-map+dp+有上下界最小流
题目描述 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面.田野上有 nn 棵许愿树,编号 1,2,3,…,n1,2,3,…,n,每棵树可以看作平面上的一个点,其中第 ii 棵树 (1≤ ...
- bzoj 4200: [Noi2015]小园丁与老司机【dp+有上下界最小流】
洛谷上有个点死活卡不过去,不知道是哪里写丑了orz 参考:https://www.cnblogs.com/ditoly/p/BZOJ4200.html 从上往下dp,设f为不向左右走直接上去的值,g为 ...
- [BZOJ]4200: [Noi2015]小园丁与老司机
Time Limit: 20 Sec Memory Limit: 512 MBSec Special Judge Description 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维 ...
随机推荐
- 开发Windows服务
在开发Windows服务时需要注意一点,如果在开发完成后,需要通过命令来进行安装的,那么在开发的时候,需要在服务类上面添加一个安装文件.如下图: 添加完成后,就 ...
- 一个体验好的Windows 任务栏缩略图开发心得
本文来自网易云社区 作者:孙有军 前言: 对于一个追求极致体验的软件来说,利用好系统的每一点优秀的特性,将会大大提高软件的品质. Windows vista以来任务栏缩略图,及Win + TAB的程序 ...
- 使用Unity创建依赖注入
这篇文章翻译自<Dependency Injection With Unity>第三章.文中提到的类似"前几节"的内容您不必在意,相信您可以看懂的. P.S:如 ...
- python学习五
打包代码与数据 数据结构要与数据匹配,数据结构影响代码的复杂性 列表 集合 字典 #创建与初始化 cleese={} cleese2=dict() cleese["name"] ...
- 「日常训练」Kefa and Company(Codeforces Round #321 Div. 2 B)
题意与分析(CodeForces 580B) \(n\)个人,告诉你\(n\)个人的工资,每个人还有一个权值.现在从这n个人中选出m个人,使得他们的权值之和最大,但是对于选中的人而言,其他被选中的人的 ...
- Java Web开发框架Spring+Hibernate整合效果介绍(附源码)(已过期,有更好的)
最近花了一些时间整合了一个SpringMVC+springAOP+spring security+Hibernate的一套框架,之前只专注于.NET的软件架构设计,并没有接触过Java EE,好在有经 ...
- [Clr via C#读书笔记]Cp5基元类型引用类型值类型
Cp5基元类型引用类型值类型 基元类型 编译器直接支持的类型,基元类型直接映射到FCL中存在的类型. 作者希望使用FCL类型名称而避免使用关键字.他的理由是为了更加的清晰的知道自己写的类型是哪种.但是 ...
- Ubuntu—查看进程并关闭进程
环境:Ubuntu终端 命令:ps -aux 功能:查看进程信息 命令:kill 进程号(PID) 功能:杀死进程
- Python变量常量及注释
一.变量命名规则1.有字母.数字.下划线搭配组合而成2.不能以数字开头,更不能全为数字3.不能用Python的关键字4.不要太长5.名字要有意义6.不要用中文7.区分大小写8.采用驼峰体命名(多个单词 ...
- Thunder团队第五周 - Scrum会议6
Scrum会议6 小组名称:Thunder 项目名称:i阅app Scrum Master:邹双黛 工作照片: 宋雨同学在拍照,所以不在照片内. 参会成员: 王航:http://www.cnblogs ...