题目大意:
给你一个7*8的网格,每个网格摆了一张牌,牌通过相邻组合成对应的编号(1到28),问你最多有多少种组合并且输出它。
思路:
参考了别人的代码,思路奇特
首先对牌的所有组合做成对应的编号,方便直接索引(二维数组实现)
应该牌只能横向或者纵向组合,设置两个方向。
dfs一列一列的搜,搜到每列最后一个元素换一行搜。
代码:

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

int a[7][8];
int vis[7][8];
int dir[2][2]={{1,0},{0,1}};
int id[7][8];
int num[30];
int ans[7][8];
int cnt;
void init(){//处理两个数字对应的多米诺卡牌编号 
	int cnt=1;
	for(int i=0;i<=6;i++){
		for(int j=i;j<=6;j++){
			id[j][i]=id[i][j]=cnt++; 
		}
	}
}
void dfs(int x,int y,int _num){
	if(_num==28){
		cnt++;
		for(int i=0;i<7;i++){
			for(int j=0;j<8;j++){
				if(ans[i][j]<10){
				    printf(" %d",ans[i][j]);
					}else
					printf(" %d",ans[i][j]);
			}
			printf("\n");
		}
		printf("\n");
		return;
	}
	if(x==7)return;//全部行搜完无需再搜 
	if(y==8){//当前列搜完,换下一列 
		dfs(x+1,0,_num);
		return;
	}
	if(vis[x][y]){//处理下一列的元素是否访问过 
		dfs(x,y+1,_num);
		return;
	}
	for(int i=0;i<2;i++){
		if (i == 0 && x == 6) continue;//如果不判这个,dfs会访问到最后一层的下一层并且全部成立(实际上那行不存在,会导致错误结果) 
		if (i == 1 && y == 7) continue;//同理 
		int fx=x+dir[i][0];
		int fy=y+dir[i][1];
		if(vis[fx][fy])continue;//(fx,fy)已经访问过 
		if(num[id[a[x][y]][a[fx][fy]]])continue;//出现重复的数字 
		ans[x][y]=ans[fx][fy]=id[a[x][y]][a[fx][fy]];
		num[id[a[x][y]][a[fx][fy]]]=vis[fx][fy]=vis[x][y]=1;
		dfs(x,y+1,_num+1);
		num[id[a[x][y]][a[fx][fy]]]=vis[fx][fy]=vis[x][y]=0;//hui'su 
	}
}
int main(){
	int k=1;
	init();
	int flag=0;
	while(scanf("%d",&a[0][0])!=EOF){
		cnt=0;
		for(int i=1;i<8;i++){
			scanf("%d",&a[0][i]);
		}
		for(int i=1;i<7;i++){
			for(int j=0;j<8;j++){
				scanf("%d",&a[i][j]);
			}
		}
		if(flag)
		printf("\n\n\n");
		printf("Layout #%d:\n\n",k);
		flag=1;
		for(int i=0;i<7;i++){
			for(int j=0;j<8;j++){
				printf(" %d",a[i][j]);
			}
			printf("\n");
		}
		printf("\n");
		printf("Maps resulting from layout #%d are:\n\n",k);
		memset(vis,0,sizeof(vis));
		memset(num,0,sizeof(num));
		dfs(0,0,0);
		printf("There are %d solution(s) for layout #%d.\n",cnt,k++);
	}
}