回溯加剪枝。只需DFS右、下兩個方向即可,可以一行一行來。弄完一行之後看下該行所有數字是否都配對了,否則剪枝。還是得細心,兩個 cnt 認錯了找了大半天 bug 。。。
#include<bits/stdc++.h>
using namespace std;
const int n = 7;
int cnt;
int dx[] = {1, 0}, dy[] = {0, 1};
int dict[n][n], G[n][n+1], M[n][n+1], vis[n][n+1], use[30];
bool judge(int x) {
for (int j = 0; j <= n; j++)
if (vis[x][j] == 0) return true;
return false;
}
void DFS(int x, int y, int cnt2){
if(cnt2 == 28){
for(int i = 0; i < n; i++){
for(int j = 0; j <= n; j++){
printf("%4d", M[i][j]);
}
putchar('\n');
}
putchar('\n');
cnt++;
return;
}
if(x == n) return;
if(y == n+1){
if (judge(x)) return;
DFS(x + 1, 0, cnt2);
return;
}
if(vis[x][y]){
DFS(x, y + 1, cnt2);
return;
}
for(int i = 0; i < 2; i++){
int nx = x + dx[i], ny = y + dy[i];
int k = dict[G[x][y]][G[nx][ny]];
if(nx == n || ny == n+1 || vis[nx][ny] || use[k]) continue;
M[x][y] = M[nx][ny] = k;
vis[x][y] = vis[nx][ny] = use[k] = 1;
DFS(x, y + 1, cnt2 + 1);
vis[x][y] = vis[nx][ny] = use[k] = 0;
}
}
int main()
{
// freopen("data.in","r",stdin);
// freopen("data.out","w",stdout);
int c = 1;
for(int i = 0; i < n; i++)
for(int j = i; j < n; j++)
dict[j][i] = dict[i][j] = c++;
int T = 0;
while(scanf("%d", &G[0][0]) != EOF){
for(int i = 0; i < n; i++){
for(int j = 0; j <= n; j++){
if(!i && !j) continue;
scanf("%d", &G[i][j]);
}
}
if(T++) printf("\n\n\n");
printf("Layout #%d:\n\n", T);
for(int i = 0; i < n; i++){
for(int j = 0; j <= n; j++){
printf("%4d", G[i][j]);
}
putchar('\n');
}
printf("\nMaps resulting from layout #%d are:\n\n", T);
cnt = 0;
DFS(0, 0, 0);
printf("There are %d solution(s) for layout #%d.\n", cnt, T);
}
return 0;
}