I'm reviewing a programming problem from a local programming contest.
You can download the problem here (pdf). It's in dutch but the pictures will help to understand it.
You receive a m*m grid as input with some pipes and some missing spots (the questionmarks). The remaining pipes have to be placed in the grid so that they connect with the others.
Each pipe is represented as a letter (see picture on page 2). The letter 'A' has value 1, 'B' has value 2, ..
I tried solving it with backtracking (it doesn't quite work yet). But since the grid can be 10x10 this will be too slow. Can someone suggest a better (faster) solution/approach?
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
#define sz(a) int((a).size())
#define pb push_back
int m, found;
string letters;
vector<int> done;
vector<string> a;
int ok(char letter, int c, int r)
{
int val = letter - 'A' + 1;
//checking if no side goes outside
if (r == 0 && (val & 1))
return 0;
if (r == m - 1 && (val & 4))
return 0;
if (c == 0 && (val & 8))
return 0;
if (c == m - 1 && (val & 2))
return 0;
//check if the side is connected the other pipe on the grid
if (r > 0 && a[r - 1][c] != '?' && (a[r - 1][c] & 4) && !(val & 1))
return 0;
if (c > 0 && a[r][c - 1] != '?' && (a[r][c - 1] & 2) && !(val & 8))
return 0;
if (r < m - 1 && a[r + 1][c] != '?' && (a[r + 1][c] & 1) && !(val & 4))
return 0;
if (c < m - 1 && a[r][c + 1] != '?' && (a[r][c + 1] & 8) && !(val & 2))
return 0;
return 1;
}
void solve(int num_placed, int pos)
{
if (found) return;
//done
if (num_placed == sz(letters)) {
for (int i = 0; i < m; ++i)
cout << a[i] << endl;
found = 1;
return;
}
int c = pos % m;
int r = pos / m;
if (a[r][c] != '?')
solve(num_placed, pos + 1);
//try all the pipes on this position
for (int i = 0; i < sz(letters); ++i) {
if (!done[i] && ok(letters[i], c, r)) {
a[r][c] = letters[i];
done[i] = 1;
solve(num_placed + 1, pos + 1);
done[i] = 0;
a[r][c] = '?';
}
}
}
int main()
{
freopen("input.txt", "r", stdin);
int n;
cin >> n;
while (n--) {
cin >> m;
cin >> letters;
cout << m << endl;
a.clear();
for (int i = 0; i < m; ++i) {
string line;
cin >> line;
a.pb(line);
}
done = vector<int>(sz(letters), 0);
found = 0;
solve(0, 0);
}
return 0;
}