题目大意:
给你一个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++);
}
}