Luo Gu P3956 "NOIP2017 popular group," "checkerboard"

Original Created: 2018-10-02 22:23:11

Three search pruning

Topic Link

Title Description

A \ (m \ times m \) board, the board each grid may be red, yellow or no color. You are now the lower right corner from the top left corner of the board most come to the board.

Any moment, you are standing position must be colored (not colorless), you can only up, down, left, and right direction. When you go to the other grid from a grid, if two cells of the same color, then you do not need to spend gold; If not, you need to spend a gold coin.

In addition, you can spend two coins at his magic to make a colorless grid temporarily become your specified color. But the magic can not be used continuously, and the duration of this magic is very short, that is, if you use this magic and went out on the grid temporarily colored, you will not be able to continue to use magic; only when you leave this position , already has come a time on a grid of colors, you can continue to use this magic, and when you leave this position (making changes to his magic colored plaid) when the grid returns to colorless.

Now you want the upper left corner of the board, most went to the bottom right corner of the board, seeking a minimum cost of gold is how much?

Input / Output Format & Sample

Input Format

The first line contains two positive integers \ (m, n-\) , separated with a space, representing the size of the board, there is the number of colors on the board grid.

The next \ (n-\) lines, each line three positive integers \ (X, Y, C \) , respectively, coordinates \ ((x, y) \ ) lattice color \ (C \) .

Wherein \ (c = 1 \) for yellow, \ (C = 0 \) for red. Separated by a space between two adjacent numbers. The coordinates of the upper left corner of the board for the \ ((1, 1) \) , the coordinates of the lower right corner of \ ((m, m) \) .

The rest of the grid on the board are colorless. Ensure the top left corner of the board, that is, \ ((1,1) \) must be colored.

Output Format

An integer representing the minimum cost of gold, if not reach, the output of -1.

SAMPLE INPUT

Case #1:

5 7
1 1 0
1 2 0
2 2 1
3 3 1
3 4 0
4 4 1
5 5 0

Case #2:

5 5
1 1 0
1 2 0
2 2 1
3 3 1
5 5 0

Sample Output

Case #1:

8

Case #2:

-1

Sample interpretation & Other notes

For \ (30 \% \) data, \ (. 1 ≤ m ≤. 5, n-≤ ≤ 10. 1 \)

For \ (60 \% \) data, \ (. 1 ≤ m ≤ 20 is,. 1 ≤ ≤ n-200 is \)

For \ (100 \% \) data, \ (. 1 ≤ m ≤ 100,. 1 ≤ 1,000 ≤ n-\)

Resolve

We do not need to maintain a certain point is passed

We need to determine the boundaries, and white squares, optimality pruning and come to an end four cases

With \ (MP \) array of FIG stored, predetermined white represents 0, 1 represents red, 2 for yellow

With \ (f_ {i, j} \) represents \ (1,1 \) to \ (i, j \) minimum cost

The main difficulty of this problem is that the added mechanisms film method

DFS then need to pass four parameters:

  • intx and y coordinates
  • intThe current number of coins used
  • boolCurrently use the Membrane

In the four-way DFS, the need to determine the following:

  • Whether the current grid color
    if no color and does not use film method, using membrane method using the number of coins +2, continue DFS;
    the absence of color and used the membrane, can not be saved
  • The current cell and the next cell color are the same color
    if the same color, for the next step DFS;
    if different colors, using the number of coins +1 continue DFS

Note that, \ (f \) array-valued to determine whether before coming to an end, after optimality pruning, otherwise I might not be the case on assignment appears

Code

/* -- Basic Headers -- */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>

/* -- STL Iterator -- */
#include <vector>
#include <string>
#include <stack>
#include <queue>

/* -- Defined Functions -- */
#define For(a,x,y) for (int a = x; a <= y; ++a)
#define Bak(a,y,x) for (int a = y; a >= x; --a)
using namespace std;

namespace FastIO {
    void DEBUG(char comment[], int x) {
        cerr << comment << x << endl;
    }

    inline int getint() {
        int s = 0, x = 1;
        char ch = getchar();
        while (!isdigit(ch)) {
            if (ch == '-') x = -1;
            ch = getchar();
        }
        while (isdigit(ch)) {
            s = s * 10 + ch - '0';
            ch = getchar();
        }
        return s * x;
    }
    inline void __basic_putint(int x) {
        if (x < 0) {
            x = -x;
            putchar('-');
        }
        if (x >= 10) __basic_putint(x / 10);
        putchar(x % 10 + '0');
    }

    inline void putint(int x, char external) {
        __basic_putint(x);
        putchar(external);
    }
}

namespace Solution {
    const int MAXM = 100 + 10;
    
    int f[MAXM][MAXM];
    int mp[MAXM][MAXM];
    #define WHITE 0
    #define RED 1
    #define YELLOW 2
    
    const int dx[5] = {0,  0, 0, -1, 1};
    const int dy[5] = {0, -1, 1,  0, 0};
    
    int m, n, ans = 2147482333;
    
    void DaFaShi(int x, int y, int nowSum, bool usedMogic) {
        // 苟利国家生死以
        // 岂因祸福避趋之
        // 你们啊,不要总是想弄个大新闻 
        // 说什么使用膜法
        // 再把我批判一番 
        if (x < 1 || y < 1 || x > m || y > m) return; // 边界 
        if (mp[x][y] == WHITE) return; // 走到白格子 
        if (nowSum >= f[x][y]) return; // 最优性剪枝 
        f[x][y] = nowSum;
        if (x == m && y == m) {
            ans = std::min(nowSum, ans);
            return;
            // 搜索完成 
        }
        
        For (i, 1, 4) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if (mp[nx][ny] != WHITE) {
                // 有颜色 
                if (mp[nx][ny] == mp[x][y]) DaFaShi(nx, ny, nowSum, false);
                // 颜色相同,继续往后搜 
                else DaFaShi(nx, ny, nowSum + 1, false); // 颜色不同,花费金币 
            } else if (mp[nx][ny] == WHITE && !usedMogic){
                // 没颜色且没用膜法 
                mp[nx][ny] = mp[x][y]; // 念诗,使用膜法 
                DaFaShi(nx, ny, nowSum + 2, true); // 使用膜法花费2金币 
                mp[nx][ny] = WHITE; // 回溯 
            }
        }
    }
}

int main(int argc, char *const argv[]) {
    #ifdef HANDWER_FILE
    freopen("testdata.in", "r", stdin);
    freopen("testdata.out", "w", stdout);
    #endif
    using namespace Solution;
    using namespace FastIO;
    memset(f, 0x7f, sizeof(f));
    m = getint();
    n = getint();
    For (i, 1, n) {
        int x, y, c;
        x = getint();
        y = getint();
        c = getint();
        mp[x][y] = c + 1;
    }
    DaFaShi(1, 1, 0, false);
    if (ans == 2147482333) puts("-1");
    else putint(ans, '\n');
    return 0;
}

Guess you like

Origin www.cnblogs.com/handwer/p/11745446.html