您的位置:首页 > 编程语言

【POJ3009 - Curling】 解题报告+思路+代码+教训(看别人的报告过的)

2012-03-11 23:15 507 查看
#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐