UVa 211

这道题只看书上的中文解释可能有些费力,理解题后还是比较简单的,对每个数字看能否与右边或下边的数字配对组成一张牌,注意加各种剪枝就行。

#include <bits/stdc++.h>
using namespace std;

int kase, solution;
int tab[10][10], res[10][10], vis[30];
int dict[7][7];
const int dir[2][2] = { { 0, 1 }, { 1, 0 } };

void init()
{
	++kase;
	solution = 0;
	memset(tab, 0, sizeof(tab));
	memset(res, 0, sizeof(res));
	memset(vis, 0, sizeof(vis));
	int cnt = 0;
	for (int i = 0; i <= 6; ++i) for (int j = i; j <= 6; ++j) dict[i][j] = ++cnt;
}
bool in()
{
	for (int i = 1; i <= 7; ++i)
        for (int j = 1; j <= 8; ++j)
            if(!(cin >> tab[i][j]))
                return false;
    if(kase>=2) printf("


");
	printf("Layout #%d:

", kase);
	for (int i = 1; i <= 7; ++i){
		for (int j = 1; j <= 8; ++j)
			printf("%4d", tab[i][j]);
		printf("
");
	}
	printf("
");
	return true;
}
void out()
{
    if(!solution)
        printf("Maps resulting from layout #%d are:
", kase);
	++solution;
	printf("
");
	for (int i = 1; i <= 7; ++i){
		for (int j = 1; j <= 8; ++j)
			printf("%4d", res[i][j]);
		printf("
");
	}
}
inline int calc(int x, int y)
{
	if (x > y) swap(x, y);
	return dict[x][y];
}
void DFS(int d, int r0, int c0)
{
	if (d == 28) {out(); return;}
	if (c0==9) c0 = 1, ++r0;
	if (res[r0][c0]){
        DFS(d, r0, c0 + 1);
        return;
	}
	for (int i = 0; i < 2; ++i){
		int r = r0 + dir[i][0], c = c0 + dir[i][1];
		if(r > 7 || c > 8 || res[r][c]) continue;
		int val = calc(tab[r0][c0], tab[r][c]);
		if (!vis[val]){
			vis[val] = 1; res[r][c] = res[r0][c0] = val;
			DFS(d + 1, r0, c0 + 1);
			vis[val] = 0; res[r][c] = res[r0][c0] = 0;
		}
	}
}
int main()
{
    ios::sync_with_stdio(false);
	while (true){
		init();
		if(!in())
            return 0;
		DFS(0, 1, 1);
		printf("
There are %d solution(s) for layout #%d.
", solution, kase);
	}
	return 0;
}


原文地址:https://www.cnblogs.com/kunsoft/p/5312720.html