#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#define INPUT
/**
Problem : poj3009
看別人的報告過得,代碼基本上相同,因爲實在不會了
Begin Time: 11th/3/2012 7:28 p.m.
End Time: 11th/3/2012 11:10 p.m.
解題報告:http://blog.csdn.net/harder2005/article/details/2816881
測試數據見Discuss
知識點:
DFS,回溯,智商!!
教訓:
這道題十分經典,簡直是“不動腦子就WA”的一道題的典範
解題報告中的代碼十分簡潔精練,十分推薦!!
1.關於搜索的選擇
雖然是最短,但是題中說了超過10次就失敗,所以暗示了使用DFS
這點跟那個Nightmare的思路是一樣的
2.關於智商
這道題中有一個Block,解題報告裏面把Block看做了是牆,但是如果判斷
沒有出maze,那麼maze[i][j] == 1.回溯的時候maze[i][j] == 0
3.關於輸入輸出
這道題解題報告十分經典的一個原因,就是mazi[i][j] = 1(能夠通過)
maze[i][j] = 0不能通過,這跟WY學長提到的memset不能設1
(否則內存變成1111111111111111)思想是一樣的
4.關於搜索
這道題說冰壺丟出去就要一直碰到Block才停下,所以有一個
while(maze[i][j])
tmp.x++....
在+完之後tmp.x--,然後判斷tmp.x + 1是否在範圍內,來判斷是否扔出了範圍
這點很贊
5.關於回溯
這題作者把_min設置爲了11,最多也就是11層,判斷每個節點p > _min的時候就回溯!
既保證了最優解,又保證了剪枝,這個思想非常贊啊
思路大概就是,每次撞牆判斷是否在範圍內,如果在範圍內那就對應的牆爲1(可以通過),然後
繼續搜索,每次搜索到了Goal就_min = min (_min,tmp.p);
而且,這道題扔出去了就搜索其他方向的思路(用了四個while循環)和其他的搜索模板給出
向量direct[4][2] = { {0,1},{0,-1},{1,0},{-1,0} };的思路不一樣
太讚了,簡直是可以作爲一個新模板,一定要好好做
*/
using namespace std;
const int c0de4fun = 30;
int maze[c0de4fun][c0de4fun];
struct Node
{
int x,y,p;
};
Node pb,pe; //point of Begin,point of End;
int _min;
int W,H,tmp;
void DFS(Node nod)
{
Node tmp,tmp1;
tmp = nod;
if ( tmp.x == pe.x && tmp.y == pe.y )
{
if ( _min > tmp.p )
{
_min = tmp.p;
}
return; ///找到更優解就回溯
}
if ( tmp.p + 1 > _min )
return ; ///這個回溯剪枝是一個Punch Point!
tmp1 = tmp;
while(maze[tmp1.x][tmp1.y])
{
tmp1.x++;
if( tmp1.x == pe.x && tmp1.y == pe.y)
{
if ( tmp1.p + 1 < _min)
{
_min = tmp1.p + 1;
}
return;
}
}
tmp1.x--; ///撞牆了
if ( tmp1.x + 1 <= H && tmp1.x != tmp.x)
{ ///沒有越界
///發生過移動
tmp1.p = tmp.p + 1;
maze[tmp1.x+1][tmp1.y] = 1;
DFS(tmp1);
maze[tmp1.x+1][tmp1.y] = 0; //回溯
}
tmp1 = tmp;
while(maze[tmp1.x][tmp1.y])
{
tmp1.y++;
if( tmp1.x == pe.x && tmp1.y == pe.y)
{
if ( tmp1.p + 1 < _min)
{
_min = tmp1.p + 1;
}
return;
}
}
tmp1.y--; ///撞牆了
if ( tmp1.y + 1 <= W && tmp1.y != tmp.y)
{ ///沒有越界
///發生過移動
tmp1.p = tmp.p + 1;
maze[tmp1.x][tmp1.y+1] = 1;
DFS(tmp1);
maze[tmp1.x][tmp1.y+1] = 0; //回溯
}
tmp1 = tmp;
while(maze[tmp1.x][tmp1.y])
{
tmp1.x--;
if( tmp1.x == pe.x && tmp1.y == pe.y)
{
if ( tmp1.p + 1 < _min)
{
_min = tmp1.p + 1;
}
return;
}
}
tmp1.x++; ///撞牆了
if ( tmp1.x - 1 > 0 && tmp1.x != tmp.x)
{ ///沒有越界
///發生過移動
tmp1.p = tmp.p + 1;
maze[tmp1.x-1][tmp1.y] = 1;
DFS(tmp1);
maze[tmp1.x-1][tmp1.y] = 0; //回溯
}
tmp1 = tmp;
while(maze[tmp1.x][tmp1.y])
{
tmp1.y--;
if( tmp1.x == pe.x && tmp1.y == pe.y)
{
if ( tmp1.p + 1 < _min)
{
_min = tmp1.p + 1;
}
return;
}
}
tmp1.y++; ///撞牆了
if ( tmp1.y - 1 > 0 && tmp1.y != tmp.y)
{ ///沒有越界
///發生過移動
tmp1.p = tmp.p + 1;
maze[tmp1.x][tmp1.y-1] = 1;
DFS(tmp1);
maze[tmp1.x][tmp1.y-1] = 0; //回溯
}
}
int main()
{
#ifdef INPUT
freopen("b:\\acm\\poj3009\\input.txt","r",stdin);
#endif
while ( scanf("%d%d",&W,&H) != EOF && W != 0 && H != 0)
{
tmp = 0;
memset(maze,0,sizeof(int)*c0de4fun*c0de4fun);
_min = 11;
for( int i = 1 ; i <= H ; i++)
{
for( int j = 1 ; j<= W; j++)
{
scanf("%d",&tmp);
maze[i][j] = 1;
if ( tmp == 1 )
{
maze[i][j] = 0;
}
if ( tmp == 3 )
{
pe.x = i;
pe.y = j;
}
if ( tmp == 2 )
{
pb.x = i;
pb.y = j;
pb.p = 0;
}
}
}
DFS(pb);
if( _min <= 10 )
{
printf("%d\n",_min);
}
else
{
printf("-1\n");
}
}
return 0;
}
【POJ3009 - Curling】 解題報告+思路+代碼+教訓(看別人的報告過的)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.