zoukankan      html  css  js  c++  java
  • UVA 12295 Optimal Symmetric Paths

    UVA_12295

        首先我们可以把线的两边对折,这样就变成了半个矩阵,同时问题就转化成了从左上角到折线的位置的最短路径的条数有多少。

        首先,我们可以用SPFA求单源最短路,这样起点到每个点的最短路就都有了。之后为了能够算出路径的条数,我们可以从起点开始,每次取栈中d[]的值最小的点出栈,然后按最短路径的走向向周围的点拓展,并将拓展成功的点入栈。

        最后,统计折线上的最短路的最小值,并把所有符合要求的路径的条数相加即可。

        这个题目用dij及优先级队列做会更简单、高效,等学完dij之后再回头做下这个题目。

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #define MAXN 110
    #define MAXD 10010
    #define INF 1000000000
    #define MOD 1000000009
    int N, a[MAXN][MAXN];
    long long int f[MAXD];
    int q[MAXD], inq[MAXD], d[MAXD], min;
    int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};
    int cmp(const void *_p, const void *_q)
    {
    int *p = (int *)_p;
    int *q = (int *)_q;
    return d[*q] - d[*p];
    }
    int init()
    {
    int i, j;
    scanf("%d", &N);
    if(!N)
    return 0;
    for(i = 0; i < N; i ++)
    for(j = 0; j < N; j ++)
    scanf("%d", &a[i][j]);
    for(i = 0; i < N; i ++)
    for(j = 0; j < N - i - 1; j ++)
    a[i][j] += a[N - 1 - j][N - 1 - i];
    return 1;
    }
    void SPFA()
    {
    int i, j, k, z, newz, x, y, newx, newy, front, rear;
    for(i = 0; i < MAXD; i ++)
    d[i] = INF;
    d[0] = a[0][0];
    memset(inq, 0, sizeof(inq));
    front = rear = 0;
    q[rear ++] = 0;
    while(front != rear)
    {
    z = q[front ++];
    if(front > N * N)
    front = 0;
    inq[z] = 0;
    x = z / N;
    y = z % N;
    if(x + y == N - 1)
    continue;
    for(i = 0; i < 4; i ++)
    {
    newx = x + dx[i];
    newy = y + dy[i];
    if(newx >= 0 && newx < N && newy >= 0 && newy < N)
    {
    newz = newx * N + newy;
    if(d[z] + a[newx][newy] < d[newz])
    {
    d[newz] = d[z] + a[newx][newy];
    if(!inq[newz])
    {
    q[rear ++] = newz;
    if(rear > N * N)
    rear = 0;
    inq[newz] = 1;
    }
    }
    }
    }
    }
    }
    void DP()
    {
    int i, j, k, top, z, x, y, newx, newy, newz;
    top = 0;
    memset(f, 0, sizeof(f));
    memset(inq, 0, sizeof(inq));
    f[0] = 1;
    inq[0] = 1;
    q[top ++] = 0;
    while(top)
    {
    z = q[-- top];
    x = z / N, y = z % N;
    if(x + y == N - 1)
    continue;
    for(i = 0; i < 4; i ++)
    {
    newx = x + dx[i];
    newy = y + dy[i];
    if(newx >= 0 && newx < N && newy >= 0 && newy < N)
    {
    newz = newx * N + newy;
    if(d[newz] == d[z] + a[newx][newy])
    {
    f[newz] = (f[newz] + f[z]) % MOD;
    if(!inq[newz])
    {
    inq[newz] = 1;
    q[top ++] = newz;
    }
    }
    }
    }
    qsort(q, top, sizeof(q[0]), cmp);
    }
    }
    void solve()
    {
    int i, j, k;
    long long int ans;
    SPFA();
    DP();
    min = INF;
    for(i = 0; i < N; i ++)
    if(d[i * N + N - 1 - i] < min)
    min = d[i * N + N - 1 - i];
    ans = 0;
    for(i = 0; i < N; i ++)
    if(d[i * N + N - 1 - i] == min)
    ans = (ans + f[i * N + N - 1 - i]) % MOD;
    printf("%lld\n", ans);
    }
    int main()
    {
    while(init())
    {
    solve();
    }
    return 0;
    }


  • 相关阅读:
    Fragment练习
    view有了父元素就不能再添加父元素
    margin与padding的不同
    BroadcastReceiver组件
    史上最著名的10个思想实验[转]

    godaddy域名空间购买波折
    碎片2
    程序员要多喝水
    google.com的首页换上了pc man游戏
  • 原文地址:https://www.cnblogs.com/staginner/p/2237176.html
Copyright © 2011-2022 走看看