POJ 3009

题目链接:http://poj.org/problem?id=3009


题目大意:在一个矩形游戏盘上,有石头,冰球,终点,起点。规则:上下左右抛出冰球,且抛出后除非碰到石头或终点,否则不停止。如果出界或者连续抛出10次以上就算失败。另外,冰球不能从紧挨着石头的一方抛出;一旦冰球碰到石头,则立即停止,石头消失,然后可以进行下一次抛出。


题目的思路是深度优先遍历,但是做了两晚也没做出来,参考网上的AC代码后,发现自己的思路是有问题。总结如下:

1. 一个最致命的问题是两个函数的返回值所表达的意思是相同的,这一定预示着程序的失败。

        2. 搜索的深度就是抛出的次数。


代码如下:


<span style="font-size:18px;">#include<stdio.h>


const int HMAX = 25;
const int WMAX = 25;
int res;
int graph[HMAX][WMAX];
int W, H, istart, jstart;
int hoff[4] = { -1, 1, 0 , 0};
int woff[4] = { 0, 0, -1, 1};


void init(){
<span style="white-space:pre">	</span>res = 2000;
<span style="white-space:pre">	</span>scanf("%d%d", &W, &H);
<span style="white-space:pre">	</span>for(int i = 0; i < H; i++){
<span style="white-space:pre">		</span>for(int j = 0; j < W; j++){
<span style="white-space:pre">			</span>scanf("%d", &graph[i][j]);
<span style="white-space:pre">			</span>if(graph[i][j] == 2){
<span style="white-space:pre">				</span>istart = i;
<span style="white-space:pre">				</span>jstart = j;
<span style="white-space:pre">				</span>graph[i][j] = 0;
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>return ;
}




void minFindGoal(int is, int js, int depth){
<span style="white-space:pre">	</span>if( depth > 10 || depth >= res ) return;  //剪枝:减掉与现有结果相同或者更大的可能情况,效果:从163ms到63ms
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>for(int k = 0; k < 4; k++){
<span style="white-space:pre">		</span>if( graph[is+hoff[k]][js+woff[k]] == 1 ) continue;


<span style="white-space:pre">		</span>int i, j;
<span style="white-space:pre">		</span>for( i = is + hoff[k], j = js + woff[k]; 0 <= i && i < H && 0 <= j && j < W && graph[i][j] == 0; i += hoff[k], j += woff[k] ){;}


<span style="white-space:pre">		</span>if( i < 0 || i >= H || j < 0 || j>= W ){
<span style="white-space:pre">			</span>continue;
<span style="white-space:pre">		</span>}


<span style="white-space:pre">		</span>if(graph[i][j] == 3){
<span style="white-space:pre">			</span>res = res < depth ? res: depth;
<span style="white-space:pre">			</span>break;                                     //剪枝:如果找到,其余方向只能是大于等于它
<span style="white-space:pre">		</span>}


<span style="white-space:pre">		</span>graph[i][j] = 0;
<span style="white-space:pre">		</span>minFindGoal(i-hoff[k], j-woff[k], depth + 1);
<span style="white-space:pre">		</span>graph[i][j] = 1;
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>return;


}






int main()
{
<span style="white-space:pre">	</span>while(1){
<span style="white-space:pre">		</span>init();
<span style="white-space:pre">		</span>if( W == 0 && H == 0 ) break; 
<span style="white-space:pre">		</span>minFindGoal(istart, jstart, 1);
<span style="white-space:pre">		</span>if( res < 2000 )
<span style="white-space:pre">			</span>printf("%d\n", res);
<span style="white-space:pre">		</span>else
<span style="white-space:pre">			</span>printf("%d\n", -1);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>return 0;
}</span>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值