POJ 3009:Curling 2.0
2017-07-30 22:05
489 查看
问题描述
冰壶游戏2.0,冰壶可以在没有墙壁的路线上沿直线前进,遇到墙壁后停止并击碎面前的墙壁,求最短几步。
解题思路
DFS,但是每次进行完一条线路的计算之后要将击碎的墙壁还原。
代码
#include <iostream>
#include <stdio.h>
using namespace std;
int board[22][22];
int starti,startj;
int sum,ans;
int direct[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int w,h;
void dfs(int i,int j,int sum)
{
//十步以上直接返回
if(sum>10)
return;
//在四个方向上探索
for(int k=0;k<4;k++)
{
int nexti=i;
int nextj=j;
//如果前方是障碍物,则跳过此方向
if(board[nexti+direct[k][0]][nextj+direct[k][1]]==1)
continue;
//如果前方不是障碍物,则继续行走
while(board[nexti+direct[k][0]][nextj+direct[k][1]]==0)
{
nexti=nexti+direct[k][0];
nextj=nextj+direct[k][1];
}
//如果前方是障碍物
if(board[nexti+direct[k][0]][nextj+direct[k][1]]==1)
{
//击碎障碍物
board[nexti+direct[k][0]][nextj+direct[k][1]]=0;
//dfs
dfs(nexti,nextj,sum+1);
//还原障碍物
board[nexti+direct[k][0]][nextj+direct[k][1]]=1;
}
//如果到达终点,且是当前最小步数,则保存
if(board[nexti+direct[k][0]][nextj+direct[k][1]]==3)
if(sum<ans)
ans=sum;
}
}
int main()
{
while(cin>>w>>h)
{
if((w==0)&&(h==0))
break;
ans=100;
//方便处理越界的情况
for(int i=0;i<=h+1;i++)
for(int j=0;j<=w+1;j++)
board[i][j]=-1;
for(int i=1;i<=h;i++)
for(int j=1;j<=w;j++)
{
cin>>board[i][j];
if(board[i][j]==2)
{
starti=i;
startj=j;
board[i][j]=0;
}
}
dfs(starti,startj,1);
if(ans>10)
ans=-1;
cout<<ans<<endl;
}
return 0;
}
问题与反思
1.刚开始的时候没有使用方向向量,导致代码冗长,以后学会了使用方向向量;
2.刚开始的时候思路混乱,判断的顺序出现了问题,导致一直死循环,借鉴了别人的代码才理清思路;
3.开始时没有想到全局变量,对于最少步数的保存写的特别混乱;
3.觉得还可以剪枝,过来时的方向在下一次计算时应该可以跳过, 但是AC之后也没有再去验证。
冰壶游戏2.0,冰壶可以在没有墙壁的路线上沿直线前进,遇到墙壁后停止并击碎面前的墙壁,求最短几步。
解题思路
DFS,但是每次进行完一条线路的计算之后要将击碎的墙壁还原。
代码
#include <iostream>
#include <stdio.h>
using namespace std;
int board[22][22];
int starti,startj;
int sum,ans;
int direct[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int w,h;
void dfs(int i,int j,int sum)
{
//十步以上直接返回
if(sum>10)
return;
//在四个方向上探索
for(int k=0;k<4;k++)
{
int nexti=i;
int nextj=j;
//如果前方是障碍物,则跳过此方向
if(board[nexti+direct[k][0]][nextj+direct[k][1]]==1)
continue;
//如果前方不是障碍物,则继续行走
while(board[nexti+direct[k][0]][nextj+direct[k][1]]==0)
{
nexti=nexti+direct[k][0];
nextj=nextj+direct[k][1];
}
//如果前方是障碍物
if(board[nexti+direct[k][0]][nextj+direct[k][1]]==1)
{
//击碎障碍物
board[nexti+direct[k][0]][nextj+direct[k][1]]=0;
//dfs
dfs(nexti,nextj,sum+1);
//还原障碍物
board[nexti+direct[k][0]][nextj+direct[k][1]]=1;
}
//如果到达终点,且是当前最小步数,则保存
if(board[nexti+direct[k][0]][nextj+direct[k][1]]==3)
if(sum<ans)
ans=sum;
}
}
int main()
{
while(cin>>w>>h)
{
if((w==0)&&(h==0))
break;
ans=100;
//方便处理越界的情况
for(int i=0;i<=h+1;i++)
for(int j=0;j<=w+1;j++)
board[i][j]=-1;
for(int i=1;i<=h;i++)
for(int j=1;j<=w;j++)
{
cin>>board[i][j];
if(board[i][j]==2)
{
starti=i;
startj=j;
board[i][j]=0;
}
}
dfs(starti,startj,1);
if(ans>10)
ans=-1;
cout<<ans<<endl;
}
return 0;
}
问题与反思
1.刚开始的时候没有使用方向向量,导致代码冗长,以后学会了使用方向向量;
2.刚开始的时候思路混乱,判断的顺序出现了问题,导致一直死循环,借鉴了别人的代码才理清思路;
3.开始时没有想到全局变量,对于最少步数的保存写的特别混乱;
3.觉得还可以剪枝,过来时的方向在下一次计算时应该可以跳过, 但是AC之后也没有再去验证。
相关文章推荐
- poj 3009 Curling 2.0(dfs)
- poj3009 Curling 2.0
- Curling 2.0--POJ 3009
- poj 3009 Curling 2.0 (dfs)
- POJ-3009-Curling 2.0
- POJ 题目3009 Curling 2.0(DFS)
- POJ 3009 Curling 2.0
- POJ3009(Curling 2.0, DFS)
- POJ-3009-Curling 2.0
- poj 3009 Curling 2.0 DFS
- poj3009——Curling 2.0
- POJ 3009-Curling 2.0(dfs+剪枝)
- [挑战程序设计竞赛] POJ 3009 - Curling 2.0
- POJ 3009 Curling 2.0
- poj 3009 Curling 2.0
- POJ 3009, Curling 2.0
- poj 3009 Curling 2.0
- 【POJ】3009 - Curling 2.0
- poj3009--Curling 2.0(搜索练习1)
- poj 3009 Curling 2.0 (dfs )