UVA 825 Walkiing on the safe side

根据地图,要求固定两点间最短路径的条数 。

这题的输入数据就是个坑,题目有没有说明数据之间有多个空格,结尾换行符之前也不止一个空格,WA了好几遍,以后这种情况看来都要默认按照多空格的情况处理了。

 

可以先利用bfs求出起点到各点的最短距离,然后dfs统计 num[x][y]表示起点到x,y的最短路径数,转移方程为 num[x][y] += num[nx][ny], nx = x +dx[k],ny = y + dy[k],

map[nx][ny] != 0.

代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <climits>
  4 #include <cstring>
  5 #include <cstdlib>
  6 #include <cmath>
  7 #include <vector>
  8 #include <queue>
  9 #include <algorithm>
 10 #define esp 1e-6
 11 #define pb push_back
 12 #define in  freopen("in.txt", "r", stdin);
 13 #define out freopen("out.txt", "w", stdout);
 14 #define print(a) printf("%d\n",(a));
 15 #define bug puts("********))))))");
 16 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
 17 #define inf 0x0f0f0f0f
 18 using namespace std;
 19 typedef long long  LL;
 20 typedef vector<int> VI;
 21 typedef pair<int, int> pii;
 22 typedef vector<pii,int> VII;
 23 typedef vector<int>:: iterator IT;
 24 #define N 200
 25 int map[N][N], vis[N][N], num[N][N];
 26 int dis[N][N];
 27 int n, m;
 28 int dx[] = {-1, 0, 1, 0};
 29 int dy[] = {0, 1, 0, -1};
 30 void init(void)
 31 {
 32     memset(map, -1, sizeof(map));
 33     memset(vis, 0, sizeof(vis));
 34     memset(num, 0, sizeof(num));
 35     memset(dis, 0, sizeof(dis));
 36 }
 37 void bfs(int x, int y)
 38 {
 39     int u = x*m+y;
 40     queue<int> q;
 41     q.push(u);
 42     vis[x][y] = 1;
 43     while(!q.empty())
 44     {
 45         int u = q.front();
 46         int x = u/m, y = u%m;
 47         q.pop();
 48 //        print(vis[0][1]) print(vis[1][0])
 49         for(int k = 0; k < 4; k++)
 50         {
 51             int nx = x + dx[k], ny = y + dy[k];
 52             if(nx >= 0 && nx < n && ny >= 0 && ny < m && !vis[nx][ny] && map[nx][ny])
 53             {
 54                 dis[nx][ny] = dis[x][y] + 1;
 55                 q.push(nx*m+ny);
 56                 vis[nx][ny] = 1;
 57             }
 58         }
 59     }
 60 }
 61 int dfs(int x, int y)
 62 {
 63     int ans = num[x][y];
 64         if(x == 0 && y == 0 && map[x][y])
 65         return num[x][y] = 1;
 66   if(ans > 0)
 67         return ans ;
 68     for(int k = 0; k < 4; k++)
 69     {
 70         int nx = x+dx[k], ny = y+dy[k];
 71         if(nx >= 0 && nx < n && ny >= 0 && ny < m && dis[nx][ny]+1 == dis[x][y] && map[nx][ny])
 72             ans += dfs(nx, ny);
 73     }
 74     return num[x][y] =  ans;
 75 }
 76 int main(void)
 77 {
 78     int T;
 79     for(int t = scanf("%d", &T); t <= T; t++)
 80     {
 81         if(t - 1)
 82             puts("");
 83         init();
 84         scanf("%d%d", &n, &m);
 85         char ch;
 86         for(int i = 0; i < n; i++)
 87         {
 88             int j;
 89             scanf("%*d");
 90             while((ch = getchar())== ' ') ;
 91             while(ch != '\n')
 92             {
 93                 ungetc(ch, stdin);
 94                 scanf("%d", &j);
 95                 while((ch = getchar()) == ' ');
 96                 map[i][j-1] = 0;
 97             }
 98         }
 99         bfs(0, 0);
100         printf("%d\n", dfs(n-1,m-1));
101     }
102     return 0;
103 }
View Code

其实可以直接用dp的这样似乎思路简单不少,不知道为什么我总是没想到这种简便方法,=、=

dp[i][j] = dp[i-1][j] + dp[i][j-1];

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值