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;
    }


  • 相关阅读:
    裴蜀定理
    上下界网络流
    寻找符合子序列要求的区间个数
    小猪分配 , 最大流
    floyd + 最大流 (奶牛分配问题)
    抛硬币问题
    消消乐
    Entity Framework(1)
    冒泡排序
    二分法查找数据
  • 原文地址:https://www.cnblogs.com/staginner/p/2237176.html
Copyright © 2011-2022 走看看