Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u
Description
On Planet MM-21, after their Olympic games this year, curling is getting popular. But the rules are somewhat different from ours. The game is played on an ice game board on which a square mesh is marked. They use only a single stone. The purpose of the game is to lead the stone from the start to the goal with the minimum number of moves.
Fig. 1 shows an example of a game board. Some squares may be occupied with blocks. There are two special squares namely the start and the goal, which are not occupied with blocks. (These two squares are distinct.) Once the stone begins to move, it will proceed
until it hits a block. In order to bring the stone to the goal, you may have to stop the stone by hitting it against a block, and throw again.
Fig. 1: Example of board (S: start, G: goal)
The movement of the stone obeys the following rules:
- At the beginning, the stone stands still at the start square.
- The movements of the stone are restricted to x and y directions. Diagonal moves are prohibited.
- When the stone stands still, you can make it moving by throwing it. You may throw it to any direction unless it is blocked immediately(Fig. 2(a)).
- Once thrown, the stone keeps moving to the same direction until one of the following occurs:
- The stone hits a block (Fig. 2(b), (c)).
- The stone stops at the square next to the block it hit.
- The block disappears.
- The stone gets out of the board.
- The game ends in failure.
- The stone reaches the goal square.
- The stone stops there and the game ends in success.
- The stone hits a block (Fig. 2(b), (c)).
- You cannot throw the stone more than 10 times in a game. If the stone does not reach the goal in 10 moves, the game ends in failure.
Fig. 2: Stone movements-
Under the rules, we would like to know whether the stone at the start can reach the goal and, if yes, the minimum number of moves required.
With the initial configuration shown in Fig. 1, 4 moves are required to bring the stone from the start to the goal. The route is shown in Fig. 3(a). Notice when the stone reaches the goal, the board configuration has changed as in Fig. 3(b).
-
-
Fig. 3: The solution for Fig. D-1 and the final board configuration
-
Input
The input is a sequence of datasets. The end of the input is indicated by a line containing two zeros separated by a space. The number of datasets never exceeds 100.
Each dataset is formatted as follows.
the width(=w) and the height(=h) of the board
First row of the board
...
h-th row of the boardThe width and the height of the board satisfy: 2 <= w <= 20, 1 <= h <= 20.
Each line consists of w decimal numbers delimited by a space. The number describes the status of the corresponding square.
0 vacant square 1 block 2 start position 3 goal position The dataset for Fig. D-1 is as follows:
6 6
1 0 0 2 1 0
1 1 0 0 0 0
0 0 0 0 0 3
0 0 0 0 0 0
1 0 0 0 0 1
0 1 1 1 1 1 -
0 1 1 1 1 1
Output
For each dataset, print a line having a decimal integer indicating the minimum number of moves along a route from the start to the goal. If there are no such routes, print -1 instead. Each line should not have any character other than this number.
Sample Input
-
2 1
3 2
6 6
1 0 0 2 1 0
1 1 0 0 0 0
0 0 0 0 0 3
0 0 0 0 0 0
1 0 0 0 0 1
0 1 1 1 1 1
6 1
1 1 2 1 1 3
6 1
1 0 2 1 1 3
12 1
2 0 1 1 1 1 1 1 1 1 1 3
13 1
2 0 1 1 1 1 1 1 1 1 1 1 3
0 0 -
-
Sample Output
1 -
4
-
-1
-
4
-
10
-
-1
-
深度深度
-
深度优先搜索,题目大意就是,有一个起始点2 有一个终点3 0表示空地 1表示墙 一开始你站在起始点扔石头
可以向上下左右四个方向扔,确定方向后,如果就在你一步远的地方是墙的话就不能扔 不是墙就能扔,扔出去的石头能够飞到无限远(如果飞过了边界,就不在飞回来,然后永远达不到终点),如果你的石头遇到了墙,就在到达墙前面的一步停下,然后墙消失。给定数据,问从起点到终点的最小扔石头次数(飘过终点就算达到终点)
这道题,我代码写糟了,bug不好找,因此发来谨记,这是最后一次,先判断在到达点进行dfs
我的,判断之后dfs(边界容易被上次数据影响从而影响正确结果,就因为没有清空数组,导致wa2)
//
// Create by 神舟 on 2015-02-20
//
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <cctype>
#include <stack>
#include <queue>
#include <map>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define CLR(x) memset(x,0,sizeof x)
#define ll long long
#define inf 0x3f3f3f3f
const int maxn=2e1+5;
const int MOD=5e5+5;
int n,m,ans;
int num[maxn][maxn],dir[4][2]={1,0,0,1,-1,0,0,-1};
void dfs(int step, int I,int J)
{
if(step>9||step>=ans) return;//剪枝
for(int i=0;i<4;i++){
int i1=I,j1=J,flag1=0,flag2=0;//flag1和flag2必须都等于1的时候,才能进行深度优先搜索
while(i1+dir[i][0]>=1&& i1+dir[i][0]<=n&&j1+dir[i][1]>=1&&j1+dir[i][1]<=m&&num[i1+dir[i][0]][j1+dir[i][1]] != 1){//先判
flag1=1;//表示并非一开始就一堵墙 ,堵到在
i1+=dir[i][0],j1+=dir[i][1];
if(num[i1][j1]==3){//飞过终点
ans=min(ans,step+1);
return;
}
}
if(num[i1 + dir[i][0]][j1 + dir[i][1]] == 1)
flag2=1;
if(flag2&&flag1){
// printf("%d %d\n",i1,j1);
num[i1+dir[i][0]][j1+dir[i][1]]=0;
dfs(step+1,i1,j1);
num[i1+dir[i][0]][j1+dir[i][1]]=1;
}
}
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
while(scanf("%d%d",&m,&n)!=EOF&&n&&m){
CLR(num);//******清零,就这一句话,天差地别
for(int i=1;i<=n;i++) for(int j=1;j<=m;scanf("%d",num[i]+j++));
ans=inf;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(num[i][j]==2){
dfs(0,i,j);
}
if(ans>10) ans=-1;
printf("%d\n",ans);
//printf("\n\n\n");
}
return 0;
}
韬韬的:
//
// POJ 3009 Curling 2.0
//
// Created by TaoSama on 2015-02-19
// Copyright (c) 2014 TaoSama. All rights reserved.
//
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
#define CLR(x,y) memset(x, y, sizeof(x))
using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;
int n, m, d[4][2] = { -1, 0, 1, 0, 0, 1, 0, -1};
char a[105][105];
int sx, sy, gx, gy, ans;//有的变量没用的。。。不要太在意 ans是最后答案
void dfs(int x, int y, int seg) {
if(seg > 10 || seg >= ans) return;//剪枝
for(int i = 0; i < 4; ++i) {
for(int j = 1;; ++j) {//for实现和我while一样的功能
int nx = x + j * d[i][0], ny = y + j * d[i][1];//管它三七21,先加上再判断这样就不会因为边界受上次影响而出错了
if(nx < 1 || nx > n || ny < 1 || ny > m) break;//越界
if(a[nx][ny] == '3') {
ans = min(ans, seg + 1);//飞过终点
return;
}
if(a[nx][ny] == '1') {//遇到墙
if(j == 1) break;//如果是人 面前一步那堵墙,
a[nx][ny] = '0';//拆墙
nx -= d[i][0], ny -= d[i][1];
dfs(nx, ny, seg + 1);
nx += d[i][0], ny += d[i][1];
a[nx][ny] = '1';//补墙
break;
}
}
}
}
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
while(cin >> m >> n && n != 0 && m != 0) {
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j) {
cin >> a[i][j];
if(a[i][j] == '2')
sx = i, sy = j;
if(a[i][j] == '3')
gx = i, gy = j;
}
}
ans = INF;
dfs(sx, sy, 0);
if(ans > 10) ans = -1;
cout << ans << endl;
}
return 0;
}