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 负责看管一片田野,田野可以看作一个二维 ...
随机推荐
- vs找不到lib以及编译的link过程中出现的问题
1.#pragma comment 程序中已经通过该语句完成lib库的引入,如果再在input里面添加lib库就会报错: 2.要在general的“导入外部库”的设置选项的目录下面添加引用到的lib库 ...
- 「日常训练」Watering Flowers(Codeforces Round #340 Div.2 C)
题意与分析 (CodeForces 617C) 题意是这样的:一个花圃中有若干花和两个喷泉,你可以调节水的压力使得两个喷泉各自分别以\(r_1\)和\(r_2\)为最远距离向外喷水.你需要调整\(r_ ...
- pycharm 3.4 亲测可使用到2019年2月的注册码,要用者从速
注册码: D87IQPUU3Q-eyJsaWNlbnNlSWQiOiJEODdJUVBVVTNRIiwibGljZW5zZWVOYW1lIjoiTnNzIEltIiwiYXNzaWduZWVOYW1l ...
- 【转】Bootstrap FileInput中文API整理
Bootstrap FileInput中文API整理 这段时间做项目用到bootstrap fileinput插件上传文件,在用的过程中,网上能查到的api都不是很全,所以想着整理一份比较详细的文档, ...
- lintcode373 奇偶分割数组
奇偶分割数组 分割一个整数数组,使得奇数在前偶数在后. 您在真实的面试中是否遇到过这个题? Yes 样例 给定 [1, 2, 3, 4],返回 [1, 3, 2, 4]. 我的方法:设定两个数组,分别 ...
- block inline 和 inline-block
概念 block和inline这两个概念是简略的说法,完整确切的说应该是 block-level elements (块级元素) 和 inline elements (内联元素). block元素通常 ...
- 将SqlDataReader 数据集转化为datatbale ,在将datatable 转化为iList
public IList GetModelList(string tablename, string where) { IList list = null; DataTable dataTable = ...
- popen()与system()
一.popen() 用途:执行shell命令(并读取其输出或向其发送一些输入) 特点:通过管道来与shell命令进行通信 二.system()
- PhotoShop基础工具 -- 移动工具
还是学点美工的东西吧, 业余爱好 比学编程还难 PS版本 : PhotoShop CS6 1. 移动工具 (1) 工具栏和属性栏 工具栏 和 属性栏 : 左侧的是工具栏, 每选中一个工具, 在菜单 ...
- 团队选题报告(i know)
一.团队成员及分工 团队名称:I know 团队成员: 陈家权:选题报告word撰写 赖晓连:ppt制作,原型设计 雷晶:ppt制作,原型设计 林巧娜:原型设计,博客随笔撰写 庄加鑫:选题报告word ...