zoukankan      html  css  js  c++  java
  • P3956 棋盘

    题目描述

    有一个m * m 的棋盘,棋盘上每一个格子可能是红色、黄色或者没有任何颜色的。你现在需要从棋盘的最左上角走到棋盘的最右下角。
    任何一个时刻,你所站在的位置必须是有颜色的(不能是无色的),你只能向上、下、左、右四个方向前进。当你从一个格子走向另一个格子时,如果两个格子的颜色相同,那你不需要花费金币;如果不同,则你需要花费1个金币。
    另外,你可以花费2个金币施展魔法让下一个无色格子暂时变为你指定的颜色。但是这个魔法不能连续使用,而且这个魔法的持续时间很短,也就是说,如果你使用了这个魔法,走到了这个暂时有颜色的格子上,你就不能继续使用魔法;只有当年离开了这个位置,走到一个本来就有颜色的格子上的时候,你才能继续使用这个魔法,而当你离开了这个位置(施展魔法使得变为有颜色的格子)时,这个格子恢复为无色。
    现在你要从棋盘的最左上角,走到棋盘的最右下角,求花费的最少金币是多少?

    输入格式:

    第一行包含连个正整数m,n以一个空格分开,分别代表棋盘的大小,棋盘上有颜色的格子的数量。
    接下来的n行,每行三个正整数x,y,c,分别表示座位为(x,y)的格子有颜色c。
    其中c=1代表黄色,c=0代表红色。相邻两个数之间用一个空格分隔开。棋盘左上角的坐标为(1,1),右下角的坐标为(m,m)。
    棋盘上其余的格子都是无色。保证棋盘的左上角,也就是(1,1)一定是有颜色的。

    输出格式:

    一个整数,表示花费的金币的最小值,如果无法到达,输出-1.

    e.g:

     

    ====================================分割线========================================

    求最小值,应该用BFS也是可以的。不过在这里我用的是DFS:遍历所有可能,取其中满足条件的最小值。

    如果每种情况我们都走到尽头的话,时间复杂度肯定会太大。因此我们可以尝试一下剪枝:

    设置一个数组money[][],其中money[x][y]表示走到(x,y)时所花费的金币(即,(x,y)这一点是可达的),那么在尝试其他路径到达(x,y)这个点时,如果花费的金币大于money[x][y],就没有继续下去的必要了;同理,当走到当前这一步,所花费的金币已经大于等于前面尝试过的满足条件的总花费时,也没有了继续下去的必要(因为即使你下面不需要花费金币,总数最多只是持平,不会更小)。

    在遇到一个没有颜色的点时,需要判断下一步是否可以使用魔法,因此可以用一个bool型的参数来记录当前是否已经使用过魔法(当然用其他类型的参数也OK)。

    实现代码如下:

    #include <iostream>
    int m, n, cost;
    int chessBoard[105][105];
    int money[105][105];
    //上,下,左,右
    const int dx[4] = {-1, 1, 0, 0};
    const int dy[4] = {0, 0, -1, 1};
    void DFS(int x, int y, int curCost, bool used);
    using namespace std;
    
    int main()
    {
        cin >> m >> n;
        //将棋盘初始化为无颜色的
        for(int r = 0; r <= m; r++){
            for(int c = 0; c <= m; c++){
                chessBoard[r][c] = -1;
                money[r][c] = 50000;
            }
        }
        for(int i = 1; i <= n; i++){
            int x, y, color;
            cin >> x >> y >> color;
            chessBoard[x][y] = color;
        }
        cost = 50000;
        DFS(1, 1, 0, false);
        if(cost == 50000)
            cout << -1 << endl;
        else
            cout << cost << endl;
        return 0;
    }
    
    void DFS(int x, int y, int curCost, bool used){
        if(x == m && y == m){
            cost = cost < curCost ? cost : curCost;
            return;
        }
        //可以先判定边界,再进去函数,应该会更快一点
        if(x < 1 || y < 1 || x > m || y > m)
            return;
        if(curCost > cost)
            return;
        if(curCost >= money[x][y])
            return;
        else
            money[x][y] = curCost;
        for(int i = 0; i < 4; i++){
            int cur_x = x + dx[i];
            int cur_y = y + dy[i];
            if(chessBoard[cur_x][cur_y] != -1){
                if(chessBoard[cur_x][cur_y] == chessBoard[x][y])
                    DFS(cur_x, cur_y, curCost, false);
                else
                    DFS(cur_x, cur_y, curCost+1, false);
            }else if(!used){
                chessBoard[cur_x][cur_y] = chessBoard[x][y];
                DFS(cur_x, cur_y, curCost+2, true);
                chessBoard[cur_x][cur_y] = -1;
            }
        }
    }
  • 相关阅读:
    背水一战 Windows 10 (90)
    背水一战 Windows 10 (89)
    背水一战 Windows 10 (88)
    背水一战 Windows 10 (87)
    背水一战 Windows 10 (86)
    背水一战 Windows 10 (85)
    背水一战 Windows 10 (84)
    背水一战 Windows 10 (83)
    背水一战 Windows 10 (82)
    背水一战 Windows 10 (81)
  • 原文地址:https://www.cnblogs.com/WakingShaw/p/13370674.html
Copyright © 2011-2022 走看看