Original Created: 2018-10-02 22:23:11
Three search pruning
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:
int
x and y coordinatesint
The current number of coins usedbool
Currently 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;
}