XJOJ - 路径数(最短路+最短路路径数量)

题目链接:点击查看

题目大意:Euphemia到一个N*N的药草田里采药,她从左上角的格子田(第一行,第一列)出发,要到达右下角(第N行,第N列)的格子田,每次她可以走到与当前格子有边相邻的格子去,但她不会走已经走过的格子,而且出于对美的要求,她走过的路径是关于 左下-右上 对角线对称的。由于地势不同,在每个格子田采药都会有一个疲劳度Tij,Euphemia想知道:有多少条合法路径,可以使得她采药的疲劳度最小。

题目分析:因为要关于副对角线对称,所以不妨直接将矩阵沿着副对角线对折,因为要求最短路,所以不妨直接求出以点(1,1)为起点的单源最短路,期间用dp维护一下最短路路径的数量,最后累加一下就好了,这个dp我是直接从网上拿的模板,迪杰斯特拉+dp

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;
      
typedef long long LL;
     
typedef unsigned long long ull;
      
const int inf=0x3f3f3f3f;
 
const int N=110;
 
const int mod=1e9+9;
 
const int b[4][2]={0,1,0,-1,1,0,-1,0};
 
int maze[N][N],n;
 
bool vis[N][N];
 
int d[N][N];
 
LL dp[N][N];
 
struct Node
{
    int x,y,w;
    Node(int X,int Y,int W)
    {
        x=X;
        y=Y;
        w=W;
    }
    bool operator<(const Node& a)const
    {
        return w>a.w;
    }
};
 
void Dijkstra()
{
    priority_queue<Node>q;
    memset(vis,false,sizeof(vis));
    memset(d,inf,sizeof(d));
    memset(dp,0,sizeof(dp));
    dp[1][1]=1;
    d[1][1]=maze[1][1];
    q.push(Node(1,1,d[1][1]));
    while(q.size())
    {
        Node cur=q.top();
        int x=cur.x,y=cur.y;
        q.pop();
        if(vis[x][y])
            continue;
        vis[x][y]=true;
        for(int i=0;i<4;i++)
        {
            int xx=x+b[i][0];
            int yy=y+b[i][1];
            if(xx<=0||yy<=0||xx>n||yy>n||xx+yy>n+1)
                continue;
            int w=maze[xx][yy];
            if(d[xx][yy]>d[x][y]+w)
            {
                d[xx][yy]=d[x][y]+w;
                dp[xx][yy]=dp[x][y];
                q.push(Node(xx,yy,d[xx][yy]));
            }
            else if(d[xx][yy]==d[x][y]+w)
                dp[xx][yy]=(dp[xx][yy]+dp[x][y])%mod;
        }
    }
}
 
int main()
{
#ifndef ONLINE_JUDGE
//    freopen("input.txt","r",stdin);
//    freopen("output.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);
    while(scanf("%d",&n)!=EOF&&n)
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&maze[i][j]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<n-i+1;j++)
                maze[i][j]+=maze[n-j+1][n-i+1];
        Dijkstra();
        int mmin=inf;//找出最短路
        for(int i=1;i<=n;i++)
            mmin=min(mmin,d[i][n-i+1]);            
        LL ans=0;//维护答案
        for(int i=1;i<=n;i++)
            if(d[i][n-i+1]==mmin)
                ans=(ans+dp[i][n-i+1])%mod;
        printf("%lld\n",ans);
    }
 
 
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    return 0;
}
发布了655 篇原创文章 · 获赞 21 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/104461035