题源:漫步校园 HDU - 1428
题目:
LL最近沉迷于AC不能自拔,每天寝室、机房两点一线。由于长时间坐在电脑边,缺乏运动。他决定充分利用每次从寝室到机房的时间,在校园里散散步。整个HDU校园呈方形布局,可划分为n*n个小方格,代表各个区域。例如LL居住的18号宿舍位于校园的西北角,即方格(1,1)代表的地方,而机房所在的第三实验楼处于东南端的(n,n)。因有多条路线可以选择,LL希望每次的散步路线都不一样。另外,他考虑从A区域到B区域仅当存在一条从B到机房的路线比任何一条从A到机房的路线更近(否则可能永远都到不了机房了…)。现在他想知道的是,所有满足要求的路线一共有多少条。你能告诉他吗?
Input
每组测试数据的第一行为n(2=<n<=50),接下来的n行每行有n个数,代表经过每个区域所花的时间t(0<t<=50)(由于寝室与机房均在三楼,故起点与终点也得费时)。
Output
针对每组测试数据,输出总的路线数(小于2^63)。
Sample Input
3
1 2 3
1 2 3
1 2 3
3
1 1 1
1 1 1
1 1 1
Sample Output
1
6
题意:
给你一个矩阵图,让你判断从图的左上端的第一个点出发到图的右下端的第一个点的最短路径有多少条;
首先要求最短路径要用到bfs,从最后一个点开始走,求出走过的终点距离每一个点的最短距离;(记录每一个点到终点的最短距离)
然后dfs,从起点开始,如果碰到下一个点的dis大于当前点,说明下一个点不能走;(走的话就距离终点愈来愈远了)用dp记录某一个点距离终点最短路径的条数;
AC代码:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
#include <stack>
#include <queue>
using namespace std;
typedef long long ll;
ll mapp[330][330];
ll dp[330][330];//记忆数组
ll dis[330][330];//记录终点到每一个点的最短距离
ll vist[330][330];
int dir[4][2]={-1,0,1,0,0,1,0,-1};
int t;
struct node
{
ll x,y;
ll s;
bool friend operator < (node a ,node b){//要用优先队列,因为地图上的每一步的步数不相同;
return a.s>b.s;
}
}h,n;
bool check(int x,int y)
{
if(x<=0||x>t||y<=0||y>t||vist[x][y]) return 0;
return 1;
}
void bfs(int x,int y,int s)//从终点开始bfs记录终点到其四周的最短路径
{
h.x=x,h.y=y,h.s=s;
priority_queue<node> q;
dis[x][y] =s;
vist[x][y] = 1;
q.push(h);
while(!q.empty())
{
h=q.top();
q.pop();
for(int i=0;i<4;i++)
{
n.x=h.x+dir[i][0];
n.y=h.y+dir[i][1];
if(check(n.x,n.y))
{
vist[n.x][n.y]=1;
n.s=h.s+mapp[n.x][n.y];
dis[n.x][n.y]=n.s;
q.push(n);
}
}
}
}
ll dfs(int x,int y)
{
if(x==t&&y==t) return 1;
if(dp[x][y]) return dp[x][y];
for(int i=0;i<4;i++)
{
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(xx<=0||xx>t||yy<=0||yy>t||dis[xx][yy]>=dis[x][y]) continue;
dp[x][y]+=dfs(xx,yy);//dp记录从当前点向四周扩散有多少条成功到达终点并且距离最短的路径
}
return dp[x][y];//返回当前点所记录的路径条数;
}
int main ()
{
while(cin >>t)
{
for(int i=1;i<=t;i++)
for(int j=1;j<=t;j++)
cin >>mapp[i][j];
memset(vist,0,sizeof vist);
memset(dp,0,sizeof dp);
bfs(t,t,mapp[t][t]);//从终点开始
cout <<dfs(1,1)<<endl;//从起点开始
}
return 0;
}
对对对 还有一个重要的地方 没看见的话能wa死…题中给的数据超级大,2^61次方,所以数组都用 long long 吧