【发布时间】:2012-03-30 04:08:51
【问题描述】:
我正在审查本地编程竞赛中的一个编程问题。
您可以下载问题here (pdf)。它是荷兰语,但图片将有助于理解它。
您收到一个 m*m 网格作为输入,其中包含一些管道和一些缺失点(问号)。 其余的管道必须放置在网格中,以便它们与其他管道连接。
每个管道都表示为一个字母(参见第 2 页的图片)。字母“A”的值为 1,“B”的值为 2,..
我尝试通过回溯来解决它(它还不能很好地工作)。但是由于网格可以是 10x10,这将太慢。 有人可以提出更好(更快)的解决方案/方法吗?
#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;
}
【问题讨论】:
-
您已链接到输入,而不是问题描述。
-
是的,你是对的。我更改了网址。
-
这个问题让我想起了NetWalk。不一样,但仍然很有趣。
-
在某处是否有一些“硬”测试数据?
标签: c++ algorithm recursion backtracking