UVA 12295

来源:互联网 发布:外置声卡 知乎 编辑:程序博客网 时间:2024/06/14 12:14


题意:给你一个矩阵,按照副对角线对称的路径从(0,0)走到(n-1,n-1)的最小价值的路径数;

矩阵的每一个点aij代表价值;


思路:将矩阵的下半部加到上半部,这样只要走到副对角线即可;

先SPFA求d[i][j]表示走到i,j这个点的最小价值,得到d[i][n-i-1]的价值,

找出最小价值minn的点(i,n-i-1),从这个点回溯到(0,0)求出有多少路径,即为答案。


#include <stdio.h>  #include <string.h>  #include <vector>  #include <queue>  #include <algorithm>  #include <iostream>using namespace std;  #define N 1005  #define INF 1000000000#define MOD 1000000009  int m[4][2]={-1,0,0,1,1,0,0,-1};int n,mat[105][105];struct node{int x,y,dis;friend bool operator<(node a,node b)  {  return a.dis > b.dis;  }  };bool Isok(int x,int y){if(x>=0&&x<n&&y>=0&&y<n&&(x+y)<n) return true;return false;}int vis[105][105],d[105][105];void SPFA()//初始d[i][j]{memset(vis,0,sizeof(vis));int i, j, dx, dy;for (i = 0; i < n; i++)for (j = 0; j < n-i; j++)d[i][j] = INF;node p,q;d[0][0]=mat[0][0];p.x=0;p.y=0;p.dis=mat[0][0];priority_queue<node>Q;Q.push(p);while(!Q.empty()){q=Q.top();Q.pop();if(vis[q.x][q.y])continue; vis[q.x][q.y]=1;for (i=0;i<4;i++){    dx=q.x+m[i][0];dy=q.y+m[i][1];if(!Isok(dx,dy))continue;if(d[dx][dy]-mat[dx][dy]>q.dis){d[dx][dy]=mat[dx][dy]+q.dis;p.x=dx;p.y=dy;p.dis=d[dx][dy];Q.push(p);}}}}int dfs(int x,int y){int res=0;if(x==0&&y==0)//搜到(0,0),则找到一条路径;return 1;for(int i=0;i<4;i++){    int dx=x+m[i][0];int dy=y+m[i][1];if(!Isok(dx,dy))continue;if(d[x][y]==d[dx][dy]+mat[x][y])//关键:要满足(x,y)的上一点是(dx,dy)    res=(res+dfs(dx,dy))%MOD;}return res;}int main(){while(scanf("%d", &n)){if(n==0) break;int i,j;for (i = 0;i < n; i++)for (j = 0;j < n;j++)scanf("%d", &mat[i][j]);for (i = 0; i < n; i++)for (j = 0; j < n-i-1; j++)mat[i][j] += mat[n-j-1][n-i-1];SPFA();int minn=INF;int ans=0;for(i=0;i<n;i++)if(d[i][n-i-1]<minn)minn=d[i][n-i-1];//找出最小的价值;for(i=0;i<n;i++)if(d[i][n-i-1]==minn)//从最小的价值往回搜ans=(ans+dfs(i,n-i-1))%MOD;printf("%d\n",ans);}return 0;}/*31 2 32 1 31 1 2*/


0 0
原创粉丝点击