题面

BZOJ权限题,洛谷链接

题解

一道二合一的题目
考虑第一问。
先考虑如何计算六个方向上的第一个点。
左右上很好考虑,只需要按照xxx或者y" role="presentation">yyy轴排序就行了。
对于454545度的斜角,两点一定在同一条直线上。
这条直线是x+y=bx+y=bx+y=b或x−y=bx−y=bx-y=b
所以按照x+yx+yx+y和x−yx−yx-y的值分类考虑,再按照顺序在xxx轴扫一遍就可以找到了。
考虑如何计算第一问的答案,我们发现y" role="presentation">yyy轴是单调不降的。
所以可以以yyy来划分截断,按照y" role="presentation">yyy轴从上往下进行转移。
设f[i]f[i]f[i]表示iii的答案,对于所有y" role="presentation">yyy值相同的点放在一起解决。
每次转移的时候,先将当前yyy相同的所有点通过左上右上和上三个方向进行转移。
然后再考虑左右的转移。因为左右转移是可以先向一个方向绕过去再走回来的,
所以考虑转移的时候需要额外注意一下。
所以再诶外设一个g" role="presentation">ggg,f[i]f[i]f[i]表示从iii出发不在同层内转移的最优答案。
g[i]" role="presentation">g[i]g[i]g[i]表示从ii<script type="math/tex" id="MathJax-Element-340">i</script>出发,先转移到同层的某个点的最优答案。

第二问
先把所有可以存在于一个最优方案下的点连边。
因为每条边都至少被覆盖一次,发现这是一个上下界网络流问题。
因为保证有解,直接解决就好了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
using namespace std;
#define ll long long
#define RG register
#define MAX 50505
#define inf 1e6
inline int read()
{RG int x=0,t=1;RG char ch=getchar();while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();if(ch=='-')t=-1,ch=getchar();while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();return x*t;
}
int n;
struct Node{int x,y,id;}p[MAX];
bool cmpx(Node a,Node b){if(a.x!=b.x)return a.x<b.x;return a.y<b.y;}
bool cmpy(Node a,Node b){if(a.y!=b.y)return a.y<b.y;return a.x<b.x;}
bool cmpn(Node a,Node b){return a.id<b.id;}
int nt[MAX][5];
map<int,int> M;
int f[MAX],g1[MAX],g2[MAX],g[MAX],zy[MAX],a[MAX];
namespace Task1
{void Getdirt(){sort(&p[1],&p[n+1],cmpx);for(int i=1;i<n;++i)if(p[i].x==p[i+1].x)nt[p[i].id][2]=p[i+1].id;for(int i=1;i<=n;++i)if(p[i].x==0){nt[0][2]=p[i].id;break;}//upM.clear();for(int i=1;i<=n;++i)//left-up{int s=p[i].x+p[i].y;if(M[s])nt[p[i].id][3]=M[s];M[s]=p[i].id;if(s==0)nt[0][3]=p[i].id;}M.clear();for(int i=n;i>=1;--i)//right-up{int s=p[i].y-p[i].x;if(M[s])nt[p[i].id][4]=M[s];M[s]=p[i].id;if(s==0)nt[0][4]=p[i].id;}}int st[MAX],top;void Output(int x,int ans){if(!ans)return;if(f[x]==ans){printf("%d ",x);Output(zy[x],ans-1);return;}int pos=a[x];while(pos>1&&p[pos-1].y==p[a[x]].y)--pos;top=0;while(p[pos].y==p[a[x]].y&&pos<=n)st[++top]=p[pos++].id;for(int i=1;i<=top;++i)if(st[i]==x){pos=i;break;}for(int i=1;i<pos;++i)if(f[st[i]]+top-i==g[x]){for(int j=pos;j<=top;++j)printf("%d ",st[j]);for(int j=pos-1;j>i;--j)printf("%d ",st[j]);Output(st[i],f[st[i]]);return;}for(int i=top;i>pos;--i)if(f[st[i]]+i-1==g[x]){for(int j=pos;j>=1;--j)printf("%d ",st[j]);for(int j=pos+1;j<i;++j)printf("%d ",st[j]);Output(st[i],f[st[i]]);return;}}void Solve(){Getdirt();sort(&p[1],&p[n+1],cmpy);for(int i=1;i<=n;++i)a[p[i].id]=i;for(int i=n,pos;i;i=pos){top=0;pos=i;while(pos&&p[pos].y==p[i].y)st[++top]=p[pos--].id;reverse(&st[1],&st[top+1]);for(int j=1;j<=top;++j)for(int k=2;k<=4;++k){int u=st[j];if(f[u]<g[nt[u][k]]+1)f[u]=g[nt[u][k]]+1,zy[u]=nt[u][k];}for(int j=1;j<=top;++j)g[st[j]]=f[st[j]];for(int j=2,nw=1;j<=top;++j){g[st[j]]=max(g[st[j]],f[st[nw]]+top-nw);if(f[st[nw]]-nw<f[st[j]]-j)nw=j;}for(int j=top-1,nw=top;j>=1;--j){g[st[j]]=max(g[st[j]],f[st[nw]]+nw-1);if(f[st[nw]]+nw<f[st[j]]+j)nw=j;}}for(int k=2;k<=4;++k)if(f[0]<=g[nt[0][k]])f[0]=g[nt[0][k]],zy[0]=nt[0][k];printf("%d\n",f[0]);Output(zy[0],f[0]);puts("");}
}
namespace Task2
{struct Line{int v,next,w;}e[MAX<<5];int h[MAX],cnt=2,M[MAX],SS,TT,S,T;inline void Add(int u,int v,int w){e[cnt]=(Line){v,h[u],w};h[u]=cnt++;e[cnt]=(Line){u,h[v],0};h[v]=cnt++;}set<pair<int,int> > SSS;bool vis[MAX];void Link(int x,int ans,bool fl){if(!ans)return;if(!fl)if(SSS.count(make_pair(x,ans)))return;if(!fl)SSS.insert(make_pair(x,ans));if(f[x]==ans&&!vis[x]){vis[x]=true;for(int k=2;k<=4;++k)if(f[x]==g[nt[x][k]]+1){Add(x,nt[x][k],inf);M[x]-=1;M[nt[x][k]]+=1;Link(nt[x][k],ans-1,1);}}if(!fl)return;vector<int> st;int top=0;st.clear();st.push_back(0);int pos=a[x];while(pos>1&&p[pos-1].y==p[a[x]].y)--pos;top=0;while(p[pos].y==p[a[x]].y&&pos<=n)st.push_back(p[pos++].id),++top;for(int i=1;i<=top;++i)if(st[i]==x){pos=i;break;}for(int i=1;i<pos;++i)if(f[st[i]]+top-i==g[x])Link(st[i],f[st[i]],0);for(int i=top;i>pos;--i)if(f[st[i]]+i-1==g[x])Link(st[i],f[st[i]],0);}int level[MAX],cur[MAX];bool bfs(int S,int T){memset(level,0,sizeof(level));level[S]=1;queue<int> Q;Q.push(S);while(!Q.empty()){int u=Q.front();Q.pop();for(int i=h[u];i;i=e[i].next)if(e[i].w&&!level[e[i].v])level[e[i].v]=level[u]+1,Q.push(e[i].v);}return level[T];}int dfs(int u,int T,int flow){if(u==T||!flow)return flow;int ret=0;for(int &i=cur[u];i;i=e[i].next){int v=e[i].v,d;if(e[i].w&&level[v]==level[u]+1){d=dfs(v,T,min(flow,e[i].w));ret+=d;flow-=d;e[i].w-=d;e[i^1].w+=d;if(!flow)break;}}return ret;}int Dinic(int S,int T){int ret=0;while(bfs(S,T)){memcpy(cur,h,sizeof(cur));ret+=dfs(S,T,inf);}return ret;}int ans,rb;void Solve(){S=n+1;T=n+2;SS=n+3;TT=n+4;f[0]+=1;g[0]=inf;Link(0,f[0],0);for(int i=0;i<=n;++i)Add(i,T,inf);for(int i=0;i<=n;++i)Add(S,i,inf);for(int i=0;i<=n;++i)if(M[i]>0)Add(SS,i,M[i]);else Add(i,TT,-M[i]);Add(T,S,inf);rb=cnt-1;Dinic(SS,TT);h[T]=e[h[T]].next;h[S]=e[h[S]].next;ans-=Dinic(T,S);ans+=e[rb].w;printf("%d\n",ans);}
}
int main()
{n=read();for(int i=1;i<=n;++i)p[i].x=read(),p[i].y=read(),p[i].id=i;Task1::Solve();Task2::Solve();return 0;
}

【BZOJ4200】【NOI2015】小园丁与老司机(动态规划,网络流)相关推荐

  1. P2304 [NOI2015] 小园丁与老司机(网络流/上下界网络流)

    P2304 [NOI2015] 小园丁与老司机 平面上有n个点,每次可以向左.右.上.左上45度.右上45度移动,然后直线移动到达第一个没有到过的点,如果没有这样的点就不能移动,求解一条最长路,然后求 ...

  2. BZOJ4200 洛谷2304 UOJ132:[NOI2015]小园丁与老司机——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4200 https://www.luogu.org/problemnew/show/P2304 ht ...

  3. 提高千倍效率的35个编码小技巧,老司机带你飞!

    点击关注公众号,实用技术文章及时了解 来源:henleylee.github.io/posts/2019/a780fcc1.html 前言 代码优化 ,一个很重要的课题.可能有些人觉得没用,一些细小的 ...

  4. mysql入门到跑路_Mysql入门二十小题(DBA老司机带你删库到跑路)2018.11.26

    1. 请介绍数据库管理系统的种类及代表产品 RDBMS: mysql oracle mssql NoSQL: redis  mongoab  memcache 2. 请简述数据库管理系统的作用 数据存 ...

  5. oracle从删库到跑路,Mysql入门二十小题(DBA老司机带你删库到跑路)2018.11.26

    1. 请介绍数据库管理系统的种类及代表产品 RDBMS: mysql oracle mssql NoSQL: redis  mongoab  memcache 2. 请简述数据库管理系统的作用 数据存 ...

  6. 年薪30W的软件测试“老司机”工作经验

    这几天,新入职的小MM提议"老司机"们把自己这些年的软件测试工作经验跟大家分享一下,让新同学学习学习,利用空闲时间我整理了一些,可能不全,勉强看看,这也算是对自己这些年的工作总结. ...

  7. 【新梦想学员干货】必看!年薪30W的软件测试“老司机”工作经验。

    这几天,新入职的小MM提议"老司机"们把自己这些年的软件测试工作经验跟大家分享一下,让新同学学习学习,利用空闲时间我整理了一些,可能不全,勉强看看,这也算是对自己这些年的工作总结. ...

  8. 名悦集团:开车从不追尾,老司机分享驾驶避免事故小知识

    听交通广播,我们几乎每天都能听到高速路上,高架桥上,上班路上发生追尾事故,有时候是个平常的上下班高峰期.很多人会纳闷,车开的好好的,怎么就会发生追尾事故呢.开车在路上,难免会有磕磕碰碰.道路千万条,安 ...

  9. 老司机都在用的浏览器,体积小功能齐全,直呼内行

    现在市面上的浏览器简直是多不胜数,虽然数量多,但是好用的并不多.尤其是某些大厂的浏览器,无用的功能越来越多,越来越臃肿,体积也越来越大,使用体验还不好,有时候甚至不如一些小众浏览器.今天给大家安利2款 ...

  10. 视频教程-老司机讲前端之微信小程序开发成语消消乐游戏视频课程-微信开发

    老司机讲前端之微信小程序开发成语消消乐游戏视频课程 中国实战派HTML5培训第一人,微软技术讲师,曾任百合网技术总监,博看文思HTML5总监.陶国荣长期致力于HTML5.JavaScript.CSS3 ...

最新文章

  1. 2018年12月,华为HCNP大面积更新题目,军哥独家解题咯
  2. Lucene+Tika 文件索引的创建与搜索
  3. django 快速实现session的操作
  4. 似然估计中为什么要取对数以GMM为例
  5. .net Mvc Controller 接收 Json/post方式 数组 字典 类型 复杂对象
  6. 十个习惯让你精通新的开发技术
  7. Modbus协议栈应用实例之五:Modbus ASCII主站应用
  8. MiniGUI编程--编辑框
  9. canvas drawImage方法不显示图片的解决方案
  10. ftp搜索文件_CrossFTP for Mac(FTP客户端)
  11. C# 使用 quartz.net 做定时任务
  12. 数据结构 以数组的形式存储数据(c语言 干货满满)
  13. linux 开根号函数,Linux里隐藏的计算器开根号,问他它的地球未解之谜吗?
  14. 为mandriva 2010 spring打包(geany-0.19.2)
  15. 期货开户对资金有要求(期货开户有条件吗)
  16. html ajax传参数 20,jQuery Ajax传参
  17. 如何在Android状态栏中隐藏图标
  18. python动态网页爬取——四六级成绩批量爬取
  19. 微信小程序:uni-app云开发的网盘助手
  20. 动态规划法解决的问题

热门文章

  1. 编程-----相反数求解算法
  2. 任正非自称不如钱伯斯!钱伯斯究竟是何许人?
  3. “只取一瓢饮”的读书
  4. 5.6 DMA 方式
  5. 计算机技术三大领域,量化投资策略的运用
  6. 在新加坡旅游过一个令你心跳加速的情人节
  7. svn 命令行使用总结
  8. 一份B站视频加速器脚本原理请查收
  9. 半圆形进度条(vue加强版)
  10. 2019辽宁公务员考试:申论突破80+学习计划第一步