【vijos】1006 晴天小猪历险记之Hill(dijkstra)

时间:2022-12-30 04:22:24

https://vijos.org/p/1006

连边后跑点权的最短路

注意连边的时候左端点可以连到下一行的右端点,右端点可以连到下一行的左端点

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <vector>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
#define mkpii make_pair<int, int>
#define pdi pair<double, int>
#define mkpdi make_pair<double, int>
#define pli pair<ll, int>
#define mkpli make_pair<ll, int>
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << (#x) << " = " << (x) << endl
#define error(x) (!(x)?puts("error"):0)
#define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
#define printarr1(a, b) for1(_, 1, b) cout << a[_] << '\t'; cout << endl
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; } const int N=1005*1005/2, oo=~0u>>2;
int ihead[N], len, cnt, d[N], vis[N], w[N];
struct dat { int to, next; }e[N<<2];
void add(int u, int v) {
e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v;
}
priority_queue<pii, vector<pii>, greater<pii> >q;
inline int id(int i, int j) { return ((i-1)+1)*(i-1)/2+j; }
void dij() {
int n=id(len, len);
for1(i, 1, n) d[i]=oo;
d[1]=0; q.push(mkpii(0, 1));
while(!q.empty()) {
int u=q.top().second, v; q.pop(); if(vis[u]) continue; vis[u]=1;
for(int i=ihead[u]; i; i=e[i].next) if(d[v=e[i].to]>d[u]+w[u]) {
d[v]=d[u]+w[u];
q.push(mkpii(d[v], v));
}
}
} int main() {
read(len);
for1(i, 1, len) {
for1(j, 1, i) {
int now=id(i, j);
read(w[now]);
if(i<len) add(now, id(i+1, j)), add(now, id(i+1, j+1));
if(i>1 && i<len && j==1) add(now, id(i+1, i+1));
if(i>1 && i<len && j==i) add(now, id(i+1, 1));
int l=j-1; if(l<1) l=i;
int r=j+1; if(r>i) r=1;
if(i!=1) add(now, id(i, l)), add(now, id(i, r));
}
}
dij();
printf("%d\n", d[id(len, 1)]+w[id(len, 1)]);
return 0;
}

  


背景

在很久很久以前,有一个动物村庄,那里是猪的乐园(^_^),村民们勤劳、勇敢、善良、团结……
不过有一天,最小的小小猪生病了,而这种病是极其罕见的,因此大家都没有储存这种药物。所以晴天小猪自告奋勇,要去采取这种药草。于是,晴天小猪的传奇故事便由此展开……

描述

这一天,他来到了一座深山的山脚下,因为只有这座深山中的一位隐者才知道这种药草的所在。但是上山的路错综复杂,由于小小猪的病情,晴天小猪想找一条需时最少的路到达山顶,但现在它一头雾水,所以向你求助。

山用一个三角形表示,从山顶依次向下有1段、2段、3段等山路,每一段用一个数字T(1<=T<=100)表示,代表晴天小猪在这一段山路上需要爬的时间,每一次它都可以朝左、右、左上、右上四个方向走。山是环形的。(注意:在任意一层的第一段也可以走到本层的最后一段或上一层的最后一段)。

晴天小猪从山的左下角出发,目的地为山顶,即隐者的小屋。

格式

输入格式

第一行有一个数n(2<=n<=1000),表示山的高度。

从第二行至第n+1行,第i+1行有i个数,每个数表示晴天小猪在这一段山路上需要爬的时间。

输出格式

一个数,即晴天小猪所需要的最短时间。

样例1

样例输入1[复制]

 
5
1
2 3
4 5 6
10 1 7 8
1 1 4 5 6

样例输出1[复制]

 
10

限制

各个测试点1s

提示

在山的两侧的走法略有特殊,请自己模拟一下,开始我自己都弄错了……

来源

Sunnypig