I have grid N × M in which each cell is coloured with one colour.
When the player clicks on any cell of the grid of colour α, the cell in the top-leftmost corner of the grid, of colour β, receives the colour α, but not only it: all those cells which are connected to the source by paths which use only the colours α or β also receive the colour α.
The connection between cells should be considered only in the horizontal and vertical directions to form the paths. For example, when the player clicks on the cell highlighted in the figure to the left, the grid receives the colouring of the figure to the right. The goal of the game is to make the grid monochromatic.
Input Description
The first line of the input consists of 2 integers N and M (1 ≤ N ≤ 4, 1 ≤ M ≤ 5), which represent respectively the number of lines and the number of columns of the grid. The N lines following describe the initial configuration of the grid, representing each colour by an integer between 0 and 9. The input does not consist of any other line.
Output Description
Print a line containing a single integer that represents the minimum number of clicks that the player must do in order to make the grid monochromatic.
Input Sample
1:
4 5
01234
34567
67890
901232:
4 5
01234
12345
23456
345673:
4 5
00162
30295
45033
01837
Output Sample
1:
12
2:
7
3:
10
I'm trying to find a solution with backtracking (Because of the time limit of 8 seconds and small size of the grid). But it is taking time limit exceeded. How can i make it faster ?
#include <stdio.h>
#include <string.h>
#include <unordered_map>
#define MAX 5
#define INF 999999999
char original_grid[MAX][MAX];
typedef int signed_integer;
signed_integer n,m,mink;
bool vst[MAX][MAX];
signed_integer flood_path[4][2] = {
{-1,0},
{1,0},
{0,1},
{0,-1}
};
//flood and paint all possible cells... the root is (i,j)
signed_integer flood_and_paint(char cur_grid[MAX][MAX],signed_integer i, signed_integer j, signed_integer beta, signed_integer alpha, signed_integer colors[]){
//invalid cell
if (vst[i][j] || i < 0 || i >= n || j < 0 || j >= m)
return 0;
//mark existent colors
colors[cur_grid[i][j]] = 1;
//only alpha and beta colors counts
if (cur_grid[i][j] != beta && cur_grid[i][j] != alpha)
return 0;
//mark (i,j) as visited and change its color
vst[i][j] = true;
cur_grid[i][j] = alpha;
//floodit !
signed_integer ret = 1;
for (signed_integer k = 0; k < 4; k++)
ret += flood_and_paint(cur_grid,i + flood_path[k][0], j + flood_path[k][1], beta, alpha, colors);
//how many cells change
return ret;
}
std::unordered_map<int,std::unordered_map<int,bool> > vst_states;
void backtrack(char cur_grid[MAX][MAX],signed_integer k,signed_integer _cont, signed_integer alpha) {
//bigger number of clicks for this solution ? ... getting back
if(k >= mink)
return;
signed_integer colors[10];
memset(vst, false, sizeof(vst));
memset(colors, 0, sizeof(colors));
signed_integer beta = cur_grid[0][0];
signed_integer cont = flood_and_paint(cur_grid, 0, 0, beta, alpha, colors);
//there are alpha colors to change and no beta colors to change
colors[alpha] = 1;
colors[beta] = 0;
colors[cur_grid[0][0]] = 0; //there is no need to visit a color equals to grid[0][0]
//all squares on same color
if (cont == n * m) {
mink = k;
return;
}
++k;//new click
//get the state of this solution... the cells are either their original colour, or the last selected colour.
//so we can represent the state with a 20 bit mask and the last color selected(alpha) ... this was a hint given to me ...cant get this solution to work on T.T
/*
int state = 0;
for (int i = 0,st = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
state |= ((cur_grid[i][j] == original_grid[i][j])<<st);
++st;
}
}
vst_states[state][alpha] = true;
*/
//visit all possible colors
char copy[MAX][MAX];
for (signed_integer c = 0; c < 10; ++c){
if (colors[c] /*&& !vst_states[state][c]*/ ) {
memcpy(copy, cur_grid,n*m*sizeof(char));
backtrack(copy,k,cont,c);
}
}
}
void cleanBuffer(){
while (getchar_unlocked() != '\n');
}
int main(void) {
char grid[MAX][MAX];
scanf("%d %d",&n,&m);
for (signed_integer i = 0; i < n; ++i) {
cleanBuffer();
for (signed_integer j = 0; j < m; ++j){
grid[i][j] = getchar_unlocked() - '0';
}
}
memcpy(original_grid, grid,n*m*sizeof(char));
mink = INF;
backtrack(grid,0, 0, grid[0][0]);
printf("%d\n",mink);
return 0;
}