首页 > 代码库 > 1797: [Noi2010]海拔

1797: [Noi2010]海拔

1797: [Noi2010]海拔

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 6  Solved: 4
[Submit][Status][Web Board]

Description

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想知道在最理想的情况下(即你可以任意假设其他路口的海拔高度),每天上班高峰期间所有人爬坡所消耗的总体力和的最小值。

Input

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

Output

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

Sample Input

1
1
2
3
4
5
6
7
8

Sample Output

3
//平面图最小割转最短路 

HINT

 

Source

技术分享
#include<cstdio>  
#include<cstring>  
#include<cstdlib>  
#include<cmath>  
#include<ctime>  
#include<iostream>  
#include<algorithm>  
#include<vector>  
#include<string>  
#include<queue>  
using namespace std;   
#define rep(i,a,b)  for(int i=a,tt=b;i<=tt;++i)  
#define drep(i,a,b) for(int i=a,tt=b;i>=tt;--i)  
#define erep(i,e,x) for(int i=x;i;i=e[i].next)  
#define irep(i,x)   for(__typedef(x.begin()) i=x.begin();i!=x.end();i++)  
#define read()  (strtol(ipos,&ipos,10))  
#define sqr(x)  ((x)*(x))  
#define pb  push_back  
#define PS  system("pause");  
typedef long long   ll;  
typedef pair<int,int> pii;  
const int oo=~0U>>2;  
const double inf=1e100;  
const double eps=1e-6;  
string name="", in=".in", out=".out";  
struct V  
{  
    int x,y,v;  
    V(){}  
    V(int _x,int _y,int _v):x(_x),y(_y),v(_v){}  
    bool operator< (const V &o)const{return v>o.v;}  
};  
priority_queue<V> q;  
int n,R,C,st,ed,size,tot,ans=oo<<1;  
int dis[508][508],map[508][508][4];  
void Push(int x,int y,int v)  
{  
    if(dis[x][y]>v)  
    {  
        dis[x][y]=v;  
        q.push(V(x,y,v));  
    }  
    if(y==1)ans=min(ans,v+map[x][y][1]);  
    if(x==n)ans=min(ans,v+map[x+1][y][0]);  
}  
void Init()  
{  
    scanf("%d",&n);  
    rep(i,1,n+1)rep(j,1,n)scanf("%d",&map[i][j][0]);  
    rep(i,1,n)rep(j,1,n+1)scanf("%d",&map[i][j][1]);  
    rep(i,1,n+1)rep(j,1,n)scanf("%d",&map[i][j][2]);  
    rep(i,1,n)rep(j,1,n+1)scanf("%d",&map[i][j][3]);  
    memset(dis,55,sizeof dis);  
    rep(i,1,n)Push(1,i,map[1][i][0]);  
    rep(i,1,n)Push(i,n,map[i][n+1][1]);  
}  
void Dijkstra()  
{  
    V p;int x,y,v;  
    while(!q.empty())  
    {  
        p=q.top();q.pop();  
        if(p.v>dis[x=p.x][y=p.y])continue;  
        v=p.v;  
        if(x>1)Push(x-1,y,v+map[x][y][2]);  
        if(x<n)Push(x+1,y,v+map[x+1][y][0]);  
        if(y>1)Push(x,y-1,v+map[x][y][1]);  
        if(y<n)Push(x,y+1,v+map[x][y+1][3]);  
    }  
}  
int main()  
{  
    Init();  
    Dijkstra();  
    printf("%d\n",ans);  
    return 0;  
}
View Code

 

1797: [Noi2010]海拔