zoukankan      html  css  js  c++  java
  • PKU 3009 Curling 2.0(穷举搜索+剪枝)

    题目链接 点击打开链接 

            题意是一块石子,从起始位置出发,题目中起始位置为2,每次移动,它会朝着某一个方向一直运动直到碰到墙或者滑出界外,或者到达终点(题目中是3表示);如果碰到墙,则相应的墙块消失,并且求停止在墙的前面一个位置,需要再次移动,直到到达目标位置。 每次移动石子,石子都会朝同一个方向移动,遇到下面情况就会停止:

             1.石子碰到墙块

             2.石子滑出界外

             3.石子到达终点

            现在要求石子从起点到达终点最少移动次数,如果移动次数大于10次或者无法移动到目标位置,则游戏失败,输出-1.  如图所示

                                                      
                                                  
            改图中S表示其实位置,G表示终止位置,题目中,墙块以1表示,S用2表示,G用3表示,空白用0表示 球碰到墙后,墙块消失,并且球会停在墙块的前面一个位置,如图:
                                             

            图1到达目标位置情况如下图,右边为最后墙的状态。

            代码如下:

            由于题目中状态数最多为20*20,可以用穷举搜索,另外加了一个剪枝,就是当移动次数大于10搜索停止。

    #include <iostream>
    #include <algorithm>
    #include <string>
    using namespace std;
    #define H 22
    #define W 22
    #define INF 0xfffffff
    
    
    int mp[H][W];
    int dir[4][2] = {{1,0}, {0,1}, {-1,0}, {0,-1}};
    int ans, m, n;
    
    inline bool isWall(int x, int y)
    {
    	if (mp[x][y] == 1) return true;
    	return false;
    }
    
    inline bool outBoard(int x, int y)
    {
    	if (x >= n || x < 0 || y >= m || y < 0)
    		return true;
    	return false;
    }
    
    inline bool target(int x, int y)
    {
    	if (mp[x][y] == 3)
    		return true;
    	return false;
    }
    
    void dfs(int x, int y, int cnt)
    {
    	if (cnt > 10 || cnt >= ans) return;
    
    	for (int i=0; i<4; i++)
    	{
    		int tx = x, ty = y;
    
    		if (outBoard(tx + dir[i][0], ty + dir[i][1]) || isWall(tx + dir[i][0], ty + dir[i][1])) 
    			continue;
    
    		while (!outBoard(tx, ty) && !isWall(tx, ty)	&& !target(tx, ty))
    		{
    			tx = tx + dir[i][0];
    			ty = ty + dir[i][1];
    		}
    
    		if (outBoard(tx, ty)) continue;
    		if (target(tx, ty)) 
    		{
    			if (cnt < ans) ans = cnt;
    			return;
    		}
    		mp[tx][ty] = 0;
    		dfs(tx-dir[i][0], ty-dir[i][1], cnt+1);
    		mp[tx][ty] = 1;
    	}
    
    
    
    }
    
    int main()
    {
    
    	while ( cin >> m >> n && m && n) 
    	{
    		for (int i=0; i<n; i++)
    			for (int j=0; j<m; j++)
    				cin >> mp[i][j];
    
    		ans = INF;
    		for (int i=0; i<n; i++)
    			for (int j=0; j<m; j++)
    				if (mp[i][j] == 2)
    				{
    					dfs(i, j, 1);
    					break;
    				}
    
    		if (ans <= 10)
    			cout << ans << endl;
    		else 
    			cout << -1 << endl;
    
    	}
    	return 0;
    }
    


     

  • 相关阅读:
    unordered_set
    树的所有实现
    各类算法模板
    单链表全部实现(绝对史上最完整 附例题)
    求最长回文子串
    无重复的最长子串
    秋叶集
    1451. 重新排列句子中的单词
    152. 乘积最大子数组
    JVM总结的部分内容
  • 原文地址:https://www.cnblogs.com/JackieZhu/p/4190454.html
Copyright © 2011-2022 走看看