洛谷 P2046 BZOJ 2007 海拔(NOI2010)

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

题目描述

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[2000010];
int cnt=1,head[2000010]={0};
void add(int u,int v,int w)
{
    e[cnt]={head[u],v,w};
    head[u]=cnt++;
}
int s,t;
int dis[2000010];
bool inq[2000010]={0};
int spfa()
{
    memset(dis,0x7f,sizeof(dis));
    queue<int> q;
    dis[s]=0;
    inq[s]=1;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        inq[u]=0;
        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]=1;
                }
            }
        }
    }
    return dis[t];
}

int main()
{
    //freopen("altitude.in","r",stdin);
    //freopen("altitude.out","w",stdout);
    scanf("%d",&n);
    s=n*n+1,t=n*n+2;
    /***从左到右***/
    for(int i=0,w;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&w);
            if(i==0)
                add(s,(j-1)*n+1,w);
            else if(i==n)
                add(j*n,t,w);
            else
                add((j-1)*n+i,(j-1)*n+i+1,w);
        }
    }
    /******/
    /***从上到下***/
    for(int i=1,w;i<=n;i++)
    {
        for(int j=0;j<=n;j++)
        {
            scanf("%d",&w);
            if(j==0)
                add(i,t,w);
            else if(j==n)
                add(s,i+n*(n-1),w);
            else
                add(j*n+i,(j-1)*n+i,w);
        }
    }
    /******/

    /***从右向左***/
    for(int i=0,w;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&w);
            if(i==0)
                add((j-1)*n+1,s,w);
            else if(i==n)
                add(t,j*n,w);
            else
                add((j-1)*n+i+1,(j-1)*n+i,w);
        }
    }
    /******/

    /***从下到上***/
    for(int i=1,w;i<=n;i++)
    {
        for(int j=0;j<=n;j++)
        {
            scanf("%d",&w);
            if(j==0)
                add(t,i,w);
            else if(j==n)
                add(i+n*(n-1),s,w);
            else
                add((j-1)*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 0;
}

 

2、堆优化的dijkstra

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>

int n;

struct Edge{
    int next,to,w;
}e[2000010];
int cnt=1,head[2000010]={0};
void add(int u,int v,int w)
{
    e[cnt]={head[u],v,w};
    head[u]=cnt++;
}
int s,t;
int dis[2000010];
bool vis[2000010]={0};
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]=0;
    std::priority_queue<P> q;
    q.push({s,0});
    while(!q.empty())
    {
        temp=q.top();
        q.pop();
        int u=temp.u,D=temp.D;
        if(vis[u]) continue;
        vis[u]=1;
        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+1,t=n*n+2;
    /***从左到右***/
    for(int i=0,w;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&w);
            if(i==0)
                add(s,(j-1)*n+1,w);
            else if(i==n)
                add(j*n,t,w);
            else
                add((j-1)*n+i,(j-1)*n+i+1,w);
        }
    }
    /******/
    /***从上到下***/
    for(int i=1,w;i<=n;i++)
    {
        for(int j=0;j<=n;j++)
        {
            scanf("%d",&w);
            if(j==0)
                add(i,t,w);
            else if(j==n)
                add(s,i+n*(n-1),w);
            else
                add(j*n+i,(j-1)*n+i,w);
        }
    }
    /******/

    /***从右向左***/
    for(int i=0,w;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&w);
            if(i==0)
                add((j-1)*n+1,s,w);
            else if(i==n)
                add(t,j*n,w);
            else
                add((j-1)*n+i+1,(j-1)*n+i,w);
        }
    }
    /******/

    /***从下到上***/
    for(int i=1,w;i<=n;i++)
    {
        for(int j=0;j<=n;j++)
        {
            scanf("%d",&w);
            if(j==0)
                add(t,i,w);
            else if(j==n)
                add(i+n*(n-1),s,w);
            else
                add((j-1)*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 0;
}

 

目录
相关文章
|
9月前
1390:食物链【NOI2001】
1390:食物链【NOI2001】
|
缓存
【八月】每日一题 - 640. 求解方程
【八月】每日一题 - 640. 求解方程
72 0
忆pta水题
本题要求编写程序,先将输入的一系列整数中的最小值与第一个数交换,然后将最大值与最后一个数交换,最后输出交换后的序列。 注意:题目保证最大和最小值都是唯一的。 输入格式: 输入在第一行中给出一个正整数N(≤10),第二行给出N个整数,数字间以空格分隔。 输出格式: 在一行中顺序输出交换后的序列,每个整数后跟一个空格。 输入样例: 5 8 2 5 1 4 结尾无空行 输出样例: 1 2 5 4 8 
洛谷 P2827 BZOJ 4721 UOJ #264 蚯蚓
题目描述 本题中,我们将用符号表示对c向下取整,例如:。 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓。 蛐蛐国里现在共有n只蚯蚓(n为正整数)。
946 0
|
人工智能 BI
洛谷 P3183 BZOJ 4562 [HAOI2016]食物链
题目描述 如图所示为某生态系统的食物网示意图,据图回答第1小题现在给你n个物种和m条能量流动关系,求其中的食物链条数。物种的名称为从1到n编号M条能量流动关系形如a1 b1a2 b2a3 b3......am-1 bm-1am bm其中ai bi表示能量从物种ai流向物种bi,注意单独的一种孤立生物不算一条食物链 输入输出格式 输入格式:   第一行两个整数n和m,接下来m行每行两个整数ai bi描述m条能量流动关系。
1007 0
|
机器学习/深度学习
洛谷 P1129 BZOJ 1059 cogs 660 [ZJOI2007]矩阵游戏
题目描述 小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏――矩阵游戏。矩阵游戏在一个N*N黑白方阵进行(如同国际象棋一般,只是颜色是随意的)。每次可以对该矩阵进行两种操作: 行交换操作:选择矩阵的任意两行,交换这两行(即交换对应格子的颜色) 列交换操作:选择矩阵的任意两列,交换这两列(即交换对应格子的颜色) 游戏的目标,即通过若干次操作,使得方阵的主对角线(左上角到右下角的连线)上的格子均为黑色。
917 0
|
算法 vr&ar 人工智能
BZOJ 2038: [2009国家集训队]小Z的袜子(hose)【莫队算法裸题&&学习笔记】
2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 9894  Solved: 4561[Submit][Status][Discuss] Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿。
1543 0
|
机器学习/深度学习
洛谷 P2742 [USACO5.1]圈奶牛Fencing the Cows
题目描述 农夫约翰想要建造一个围栏用来围住他的奶牛,可是他资金匮乏。他建造的围栏必须包括他的奶牛喜欢吃草的所有地点。对于给出的这些地点的坐标,计算最短的能够围住这些点的围栏的长度。 输入输出格式 输入格式:   输入数据的第一行包括一个整数 N。N(0
973 0