POJ 3009 Curling 2.0

题目链接:https://vjudge.net/problem/POJ-3009

题目大意:

  冰壶比赛。

给定一个 n * m 的矩阵A,其中:

  1. A[i][j] == 0,代表通路。
  2. A[i][j] == 1,代表冰块。
  3. A[i][j] == 2,代表冰壶起点。
  4. A[i][j] == 3,代表冰壶所要到达的点。

冰壶只能往上下左右四个方向移动,且碰到冰块才会停下来,同时冰块也会碎掉,冰壶也随之停在原地,冰壶一旦打出界,比赛就结束了,冰壶只要在10步以内经过终点,就算成功。

求每场冰壶比赛的最小移动步数。

分析:

  dfs基础题,读懂题目最重要。

代码如下:

  1 //#include <bits/stdc++.h>
  2 
  3 // POJ 用 start 
  4 #include<cstdio>  
  5 #include<cstring>  
  6 #include<algorithm>  
  7 #include<iostream>  
  8 #include<string>  
  9 #include<vector>  
 10 #include<stack>  
 11 #include<bitset>  
 12 #include<cstdlib>  
 13 #include<cmath>  
 14 #include<set>  
 15 #include<list>  
 16 #include<deque>  
 17 #include<map>  
 18 #include<queue>  
 19 // POJ 用 end 
 20 
 21 using namespace std;
 22 
 23 /*-------------------Define Start-------------------*/
 24 typedef bool BL;                        // 布尔类型
 25 typedef char SB;                        // 有符号1字节,8位
 26 typedef unsigned char UB;                // 无符号1字节,8位
 27 typedef short SW;                        // 有符号短整型,16位
 28 typedef unsigned short UW;                // 无符号短整型,16位
 29 typedef long SDW;                        // 有符号整型,32位
 30 typedef unsigned long UDW;               // 无符号整型,32位
 31 typedef long long SLL;                    // 有符号长整型,64位
 32 typedef unsigned long long ULL;            // 无符号长整型,64位
 33 typedef char CH;                        // 单个字符
 34 typedef float R32;                        // 单精度浮点数
 35 typedef double R64;                        // 双精度浮点数
 36 
 37 #define Rep(i, n) for (register SDW i = 0; i < (n); ++i)
 38 #define For(i, s, t) for (register SDW i = (s); i <= (t); ++i)
 39 #define rFor(i, t, s) for (register SDW i = (t); i >= (s); --i)
 40 #define foreach(i, c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
 41 #define ms0(a) memset(a,0,sizeof(a))
 42 #define msI(a) memset(a,0x7f,sizeof(a))
 43 #define LOWBIT(x) ((x)&(-x))
 44 
 45 #define MP make_pair
 46 #define PB push_back
 47 #define ft first
 48 #define sd second
 49 
 50 #define pr(x) cout << #x << " = " << x << "  "
 51 #define prln(x) cout << #x << " = " << x << endl
 52 
 53 const ULL mod = 1e9 + 7;                //常用模数(可根据题目需要修改)
 54 const ULL inf = 0x7fffffff;                //用来表示无限大
 55 const ULL infLL = 0x7fffffffffffffffLL;    //用来表示无限大
 56 /*-------------------Define End-------------------*/
 57 
 58 struct Point{
 59     SDW X, Y;
 60     
 61     Point(SDW x = 0, SDW y = 0) : X(x), Y(y) {}
 62     
 63     void set(SDW x, SDW y) {
 64         X = x;
 65         Y = y;
 66     }
 67     
 68     Point operator+ (const Point& x) { return Point(X + x.X, Y + x.Y); }
 69     BL operator== (const Point& x) const { return X == x.X && Y == x.Y; }
 70     BL operator!= (const Point& x) const { return !(*this == x); }
 71 }; 
 72 
 73 const UDW maxN = 2e1 + 7;
 74 SDW N, M;
 75 SDW field[maxN][maxN];
 76 Point S, G;
 77 Point dir[] = {Point(0, -1), Point(-1, 0), Point(0, 1), Point(1, 0)};
 78 SDW ans;
 79 
 80 void input(){
 81     ans = inf;
 82     Rep(i, N) {
 83         Rep(j, M) {
 84             cin >> field[i][j];
 85             if(field[i][j] == 2) {
 86                 S.set(i, j);
 87             }
 88             if(field[i][j] == 3) {
 89                 G.set(i, j);
 90             }
 91         }
 92     }
 93 }
 94 
 95 BL isPass(Point x, Point y) {
 96     if(x.X == y.X) {
 97         return x.X == G.X && min(x.Y, y.Y) <= G.Y && G.Y <= max(x.Y, y.Y);
 98     }
 99     else {
100         return x.Y == G.Y && min(x.X, y.X) <= G.X && G.X <= max(x.X, y.X);
101     }
102 } 
103 
104 // 查找冰壶所能移动到的最左位置 
105 Point leftMost(Point x) {
106     while(x.Y > 0 && field[x.X][x.Y - 1] != 1) {
107         --x.Y;
108     }
109     return x;
110 }
111 
112 // 查找冰壶所能移动到的最上位置 
113 Point upMost(Point x) {
114     while(x.X > 0 && field[x.X - 1][x.Y] != 1) {
115         --x.X;
116     }
117     return x;
118 }
119 
120 // 查找冰壶所能移动到的最右位置 
121 Point rightMost(Point x) {
122     while(x.Y < M - 1 && field[x.X][x.Y + 1] != 1) {
123         ++x.Y;
124     }
125     return x;
126 }
127 
128 // 查找冰壶所能移动到的最下位置 
129 Point downMost(Point x) {
130     while(x.X < N - 1 && field[x.X + 1][x.Y] != 1) {
131         ++x.X;
132     }
133     return x;
134 }
135 
136 Point (*func[4])(Point) = {leftMost, upMost, rightMost, downMost};
137 
138 void dfs(Point p, SDW cnt) {
139     if(cnt > 10) {
140         return;
141     }
142     
143     Rep(i, 4) {
144         Point nextP = func[i](p);        // 冰壶的下一个出发点 
145         Point blockP = nextP + dir[i];    // 冰壶撞到的冰块的位置或者边界位置 
146         
147         if(isPass(p, nextP)) {             // 经过了目标点 
148             ans = min(ans, cnt + 1);
149             return;
150         }
151         if(p != nextP && blockP.X >= 0 && blockP.X < N && blockP.Y >= 0 && blockP.Y < M) {
152             field[blockP.X][blockP.Y] = 0;
153             dfs(nextP, cnt + 1);
154             field[blockP.X][blockP.Y] = 1;
155         }
156     }
157 }
158 
159 void solve(){
160     dfs(S, 0);
161     if(ans > 10) {
162         ans = -1;
163     }
164 }
165 
166 void output(){
167     cout << ans << endl;
168 }
169 
170 int main() {
171     while((cin >> M >> N) && M) {
172         input();
173         solve();
174         output();
175     }
176     return 0;
177 }
View Code
原文地址:https://www.cnblogs.com/zaq19970105/p/10803395.html