题目描述

YT市是一个规划良好的城市,城市被东西向和南北向的主干道划分为n×n个区域。简单起见,可以将YT市看作 一个正方形,每一个区域也可看作一个正方形。从而,YT城市中包括(n+1)×(n+1)个交叉路口和2n×(n+1)条双向道路(简称道路),每条双向 道路连接主干道上两个相邻的交叉路口。下图为一张YT市的地图(n = 2),城市被划分为2×2个区域,包括3×3个交叉路口和12条双向道路。

小Z作为该市的市长,他根据统计信息得到了每天上班高峰期间YT市每条道路两个方向的人流量,即在高峰期间沿 着该方向通过这条道路的人数。每一个交叉路口都有不同的海拔高度值,YT市市民认为爬坡是一件非常累的事情,每向上爬h的高度,就需要消耗h的体力。如果 是下坡的话,则不需要耗费体力。因此如果一段道路的终点海拔减去起点海拔的值为h(注意h可能是负数),那么一个人经过这段路所消耗的体力是max{0, h}(这里max{a, b}表示取a, b两个值中的较大值)。

小Z还测量得到这个城市西北角的交叉路口海拔为0,东南角的交叉路口海拔为1(如上图所示),但其它交叉路口的海拔高度都无法得知。小Z想知道在最理想的情况下(即你可以任意假设其他路口的海拔高度),每天上班高峰期间所有人爬坡消耗的总体力和的最小值。

输入输出格式

输入格式:

第一行包含一个整数n,含义如上文所示。

接下来4n(n + 1)行,每行包含一个非负整数分别表示每一条道路每一个方向的人流量信息。输入顺序:n(n + 1)个数表示所有从西到东方向的人流量,然后n(n + 1)个数表示所有从北到南方向的人流量,n(n + 1)个数表示所有从东到西方向的人流量,最后是n(n + 1)个数表示所有从南到北方向的人流量。对于每一个方向,输入顺序按照起点由北向南,若南北方向相同时由西到东的顺序给出(参见样例输入)。

输出格式:

仅包含一个数,表示在最理想情况下每天上班高峰期间所有人爬坡所消耗的总体力和(即总体力和的最小值),结果四舍五入到整数。

输入输出样例

输入样例#1:

1
1
2
3
4
5
6
7
8
输出样例#1:

3

说明

对于20%的数据:n ≤ 3;

对于50%的数据:n ≤ 15;

对于80%的数据:n ≤ 40;

对于100%的数据:1 ≤ n ≤ 500,0 ≤ 流量 ≤ 1,000,000且所有流量均为整数。

吐槽

  吐槽恶心的输入……

  BZOJ所有点一起评测,算总时间,我写spfa跑了8000+ms,交到洛谷上就TLE了两个点,给spfa加了SLF优化,依然只能8个点,再去大牛分站开O2,过了9个点。假设BZOJ和洛谷给我评测的那台评测机速度一样,洛谷#1到#9我总共跑了1500ms左右,那么#10我的要跑6000ms+啊,害怕……

  spfa的LLL优化写这题得不偿失,代码长了容易错,反正也没负边权,就写了dijkstra,我用了最裸的堆优化,在洛谷主站(无O2)跑了1137ms,当时洛谷rank24,再去大牛分站开O2跑一波,409ms,正好rank10,看了看rank1的200+ms,那位dalao用的是algorithm里的heap,好像这玩意跑得比手写二叉堆还快,过几天学一下,不知道可不可以像pb_ds中的配对对一样无脑替代priority_queue。虽然平板电视里的配对堆快得多,但我嫌pb_ds使用方法过于复杂,单词太难背了……

解题思路

  像BZOJ 1001狼爪兔子一样,本来是求原图最大流,但数据范围过大,会被卡。由于两题的图都是平面图,所以可以建对偶图,然后在对偶图上跑最短路(最小割)

源代码

1、spfa加SLF优化//不加这个优化在BZOJ、cogs上都能过了

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; int n; struct Edge{
int next,to,w;
}e[];
int cnt=,head[]={};
void add(int u,int v,int w)
{
e[cnt]={head[u],v,w};
head[u]=cnt++;
}
int s,t;
int dis[];
bool inq[]={};
int spfa()
{
memset(dis,0x7f,sizeof(dis));
queue<int> q;
dis[s]=;
inq[s]=;
q.push(s);
while(!q.empty())
{
int u=q.front();q.pop();
inq[u]=;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to,w=e[i].w;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(!inq[v])
{
q.push(v);
inq[v]=;
}
}
}
}
return dis[t];
} int main()
{
//freopen("altitude.in","r",stdin);
//freopen("altitude.out","w",stdout);
scanf("%d",&n);
s=n*n+,t=n*n+;
/***从左到右***/
for(int i=,w;i<=n;i++)
{
for(int j=;j<=n;j++)
{
scanf("%d",&w);
if(i==)
add(s,(j-)*n+,w);
else if(i==n)
add(j*n,t,w);
else
add((j-)*n+i,(j-)*n+i+,w);
}
}
/******/
/***从上到下***/
for(int i=,w;i<=n;i++)
{
for(int j=;j<=n;j++)
{
scanf("%d",&w);
if(j==)
add(i,t,w);
else if(j==n)
add(s,i+n*(n-),w);
else
add(j*n+i,(j-)*n+i,w);
}
}
/******/ /***从右向左***/
for(int i=,w;i<=n;i++)
{
for(int j=;j<=n;j++)
{
scanf("%d",&w);
if(i==)
add((j-)*n+,s,w);
else if(i==n)
add(t,j*n,w);
else
add((j-)*n+i+,(j-)*n+i,w);
}
}
/******/ /***从下到上***/
for(int i=,w;i<=n;i++)
{
for(int j=;j<=n;j++)
{
scanf("%d",&w);
if(j==)
add(t,i,w);
else if(j==n)
add(i+n*(n-),s,w);
else
add((j-)*n+i,j*n+i,w);
}
}
/******/
/*for(int i=1;i<=n*n+2;i++)
{
for(int j=head[i];j;j=e[j].next)
printf("%d=>%d %d\n",i,e[j].to,e[j].w);
}*///输出建好的图
/***没啦***/
printf("%d\n",spfa());
return ;
}

2、堆优化的dijkstra

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm> int n; struct Edge{
int next,to,w;
}e[];
int cnt=,head[]={};
void add(int u,int v,int w)
{
e[cnt]={head[u],v,w};
head[u]=cnt++;
}
int s,t;
int dis[];
bool vis[]={};
struct P{
int u,D;
bool operator < (const P & a)const{
return D>a.D;
}
}temp;
int dijkstra()
{
memset(dis,0x7f,sizeof(dis));
dis[s]=;
std::priority_queue<P> q;
q.push({s,});
while(!q.empty())
{
temp=q.top();
q.pop();
int u=temp.u,D=temp.D;
if(vis[u]) continue;
vis[u]=;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(dis[v]>D+e[i].w)
{
dis[v]=D+e[i].w;
q.push({v,dis[v]});
}
}
}
return dis[t];
} int main()
{
//freopen("altitude.in","r",stdin);
//freopen("altitude.out","w",stdout);
scanf("%d",&n);
s=n*n+,t=n*n+;
/***从左到右***/
for(int i=,w;i<=n;i++)
{
for(int j=;j<=n;j++)
{
scanf("%d",&w);
if(i==)
add(s,(j-)*n+,w);
else if(i==n)
add(j*n,t,w);
else
add((j-)*n+i,(j-)*n+i+,w);
}
}
/******/
/***从上到下***/
for(int i=,w;i<=n;i++)
{
for(int j=;j<=n;j++)
{
scanf("%d",&w);
if(j==)
add(i,t,w);
else if(j==n)
add(s,i+n*(n-),w);
else
add(j*n+i,(j-)*n+i,w);
}
}
/******/ /***从右向左***/
for(int i=,w;i<=n;i++)
{
for(int j=;j<=n;j++)
{
scanf("%d",&w);
if(i==)
add((j-)*n+,s,w);
else if(i==n)
add(t,j*n,w);
else
add((j-)*n+i+,(j-)*n+i,w);
}
}
/******/ /***从下到上***/
for(int i=,w;i<=n;i++)
{
for(int j=;j<=n;j++)
{
scanf("%d",&w);
if(j==)
add(t,i,w);
else if(j==n)
add(i+n*(n-),s,w);
else
add((j-)*n+i,j*n+i,w);
}
}
/******/
/*for(int i=1;i<=n*n+2;i++)
{
for(int j=head[i];j;j=e[j].next)
printf("%d=>%d %d\n",i,e[j].to,e[j].w);
}*///输出建好的图
/***没啦***/
printf("%d\n",dijkstra());
return ;
}

洛谷 P2046 BZOJ 2007 海拔(NOI2010)的更多相关文章

  1. 洛谷 P3307: bzoj 3202: [SDOI2013] 项链

    题目传送门:洛谷P3307.这题在bzoj上是权限题. 题意简述: 这题分为两个部分: ① 有一些珠子,每个珠子可以看成一个无序三元组.三元组要满足三个数都在$1$到$m$之间,并且三个数互质,两个珠 ...

  2. 洛谷 4106 / bzoj 3614 [HEOI2014]逻辑翻译——思路+类似FWT

    题目:https://www.luogu.org/problemnew/show/P4106 https://www.lydsy.com/JudgeOnline/problem.php?id=3614 ...

  3. 洛谷 P3332 BZOJ 3110 [ZJOI2013]K大数查询

    题目链接 洛谷 bzoj 题解 整体二分 Code #include<bits/stdc++.h> #define LL long long #define RG register usi ...

  4. 洛谷 P2486 BZOJ 2243 [SDOI2011]染色

    题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221” ...

  5. 洛谷 P2827 BZOJ 4721 UOJ #264 蚯蚓

    题目描述 本题中,我们将用符号表示对c向下取整,例如:. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现在共有n只蚯蚓(n为正整数).每只 ...

  6. 洛谷 P2155 BZOJ 2186 codevs 2301 [SDOI2008]沙拉公主的困惑

    题目描述 大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞票.房地产第一大户沙拉公主决定预测一下大富翁国现在所有真钞票的 ...

  7. 洛谷 P1903 BZOJ 2120 清橙 A1274【模板】分块/带修改莫队(数颜色)(周奕超)

    试题来源 2011中国国家集训队命题答辩 题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔 ...

  8. 洛谷 P2709 BZOJ 3781 小B的询问

    题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求$\sum_1^Kc_i^2$的值,其中$c_i$表示数字i在[L..R]中的重复次数.小B请 ...

  9. 洛谷 P2587 BZOJ 1034 [ZJOI2008]泡泡堂

    题目描述 //不知道为什么BZOJ和洛谷都没有这幅图了,大牛们几年前的博客上都有这幅图的,把它贴上来吧 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省 ...

随机推荐

  1. 【字符串处理】关于KMP算法输出的是什么&代码

    输入: ABCDABTBD_TISABCDABCABCDABC q为当前nxt处理的模版文本串下标: k为“失配时去哪里”,详情请看注释. --------------我是求完nxt的分界线----- ...

  2. Delphi7中单元文件内各个部分的执行顺序

    注:本文主要是讨论delphi程序启动时和退出时的执行顺序,期间有些知识来源于Delphi帮助,有些来自<Delphi7程序设计教程>(这本书只告诉我有initialization 和 f ...

  3. vim copy termi

    用vim写代码时,经常遇到这样的场景,复制多行,然后粘贴. 这样做:1. 将光标移动到要复制的文本开始的地方,按v进入可视模式.2. 将光标移动到要复制的文本的结束的地方,按y复制.此时vim会自动将 ...

  4. ubuntu下C程序的编辑、编译、运行

    均以hello world程序为例 一.vim hello.c/hello.cpp 创建hello.c/hello.cpp文件,并进入vim界面 二.此时按键盘上的很多键均不会有任何反应,键入i,进入 ...

  5. 微信小程序初探(一、简单的数据请求)

    微信小程序出来有一段时间了,之前没看好小程序(觉得小程序体验不咋好,内心对新事物有抵触心里,请原谅我的肤浅[捂脸][捂脸]),不过后来偶然之间玩过小程序的游戏(跳一跳.球球大作战.猜画小歌 等),顿悟 ...

  6. Android内存解析(二)— 详解内存,内部存储和外部存储

    总述 觉得十分有必要搞清楚内存,内部存储和外部存储的区别,还有我们在开发中真正将数据存在了手机的哪儿. 先提一个问题:手机设置的应用管理中,每个App下都有清除数据和清除缓存,清除的分别是哪里的数据? ...

  7. 【BZOJ 1572】 工作安排

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1572 [算法] 贪心 先将这些工作按截至时间排序 建立一个小根堆,当决策是否完成一项 ...

  8. prim解决最小生成树问题

    #include <iostream> #include <algorithm> #include <stdio.h> #include <math.h> ...

  9. MarkDown流程图概要

    要素 流程元素定义: 名称=>类型: 显示名称 控制流程定义: 名称1([yes,no],right)->名称2 注意事项 流程元素定义在代码上部, 流程走向定义在代码下部 名称可以取中文 ...

  10. Y - Anton and Letters

    Problem description Recently, Anton has found a set. The set consists of small English letters. Anto ...