zzuli 2187 我觉得自己跑得很快 (Dijkstra + 链式前向星)

来源:互联网 发布:钓鱼台工作 知乎 编辑:程序博客网 时间:2024/04/30 06:27

传送门
某大佬zyf出的神题

Description

As we all know, the… 算了,我英语不好,题目很简单,我们有一个N层的数字塔,塔上每一个格子都有一个bad值,下图展示了一个N=4的数字塔:

当我们进入某个格子时就会获得对应的bad值,我们每次只能向下或者向右下移动一个格子。等等,当时讲动态规划用的不就是这个例题,我还记得它的状态转移方程,这是不是太easy了?
那好吧,来增加一点点难度,我们每次不仅可以向下,向右下移动,还可以向左或者向右移动一个格子,但是不能越界。一开始我们的ssh学长在第一行第一列,他想走到最后一行,但是我们的ssh学长不喜欢bad,他想使得走到最后一行时获得的bad值的和最小,当然最后一行的bad值也要算上。
现在他把这个问题交给你,想让你计算出他最小能获得多少bad值,以及他获得最小bad值时是位于最后一行的哪一列。
Input

第一行一个整数N(1<=N<=1000)。
接下来N行,第i行有i个整数wi1 wi2 … wii,wij表示第i行第j列的格子对应的bad值。
Output

一行两个整数,第一个整数是最小的bad值的和,第二个整数是ssh学长最后的位置,只需要输出该位置是第N行的第几列即可。如果答案不唯一,输出列编号最小的位置。
Sample Input

4
1
2 2
3 4 5
4 5 6 7
Sample Output

10 1
HINT

Source

看上去是dp,实际是最短路,,,好像有人dp过了,把每二位点用(i-1)* + j转成点,然后把边连上,脑洞挺大。。不过用读入优化的时候要考虑空格的问题,因为数据每行最后多一个空格

代码如下:

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<vector>#include<string>#include<algorithm>#include<queue>using namespace std;const int MAX = 1000010;const int INF = 0x3f3f3f3f;int num[MAX],head[MAX],N;//直接把点的权值存放到num里面struct Edge{    int to,cost;    int next;};struct Edge rng[4*MAX];int cnt;void add(int u,int v){    rng[cnt].to = v;    rng[cnt].next = head[u];    head[u] = cnt++;}int dis[MAX];typedef pair<int,int> P;struct Rule{    bool operator()(const int &a,const int &b) const{        return dis[a] > dis[b];    }};void Dijkstra(){    priority_queue<int,vector<int>,Rule> q;//这里最好重载下吧,我用pair的时候用greater会超时    fill(dis+1,dis+1+N*N,INF);    dis[1] = num[1];    q.push(1);    while(!q.empty()){        int x = q.top();q.pop();        for(int k=head[x];k != -1;k = rng[k].next){            int to = rng[k].to;            if(dis[to] > dis[x] + num[to]){                dis[to] = dis[x] + num[to];                q.push(to);            }        }    }}int main(void){    scanf("%d",&N);    memset(head,-1,sizeof(head));    int u,v;    for(int i=1;i<=N;i++){        for(int j=1;j<=i;j++){            scanf("%d",&num[(i-1)*N+j]);            u = (i-1)*N + j;//合并与其相连的四个点            if(j > 1){                v = (i-1)*N + j-1;                add(u,v);            }            if(j < i){                v = (i-1)*N + j+1;                add(u,v);            }            v = i*N + j;            add(u,v);            v = i*N + j+1;            add(u,v);        }    }    Dijkstra();    int f = -1,c = -1;    for(int i=(N-1)*N+1;i<=N*N;i++){        if(f == -1 || dis[i] < dis[f]){            f = i;            c = i - (N-1)*N;        }    }    printf("%d %d\n",dis[f],c);}
原创粉丝点击