题目要求:
剪邮票
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
解题思路:DFS,先找出五个点再判断是否符合题目要求
建立一个map一维数组,同时重构该数组,确保一个点上下相邻点距离为+5,-5,左右相邻点距离为+1,-1;同时也能确保换行之后相差不为1
不用设置回溯出口
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define ll long long
#define INF 0x3f3f3f3f
#define MAXSIZE 10050
using namespace std;
int record[5];//存储当前五个点信息
int map[12]={1,2,3,4,6,7,8,9,11,12,13,14};
bool mark[5]={false};//代表record中点是否被遍历
int aa[4]={-1,1,5,-5};//向四个方向遍历
int sum=0;
void dfs_camp_1(int k)
{
for(int i=0;i<4;i++)
{
int tot=record[k]+aa[i];
if(tot<1||tot>14||tot==5||tot==10) continue; //判断是否越界
for(int j=0;j<5;j++)//遍历record数组
{
if(record[j]==record[k]+aa[i]&&!mark[j])//若该点跟record[k]相邻且未遍历过
{
mark[j]=true;
dfs_camp_1(j);
}
}
}
}
int main()
{
for(int i=0;i<12;i++)
for(int j=i+1;j<12;j++)
for(int k=j+1;k<12;k++)
for(int p=k+1;p<12;p++)
for(int q=p+1;q<12;q++)
{
record[0]=map[i];
record[1]=map[j];
record[2]=map[k];
record[3]=map[p];
record[4]=map[q];
memset(mark,false,sizeof(mark));
mark[0]=true;
dfs_camp_1(0);
//dfs_camp_2(0);
bool flag=true;
for(int x=0;x<5;x++)
{
if(!mark[x]){
flag=false;
break;
}
}
if(flag)
{
for(int x=0;x<5;x++)
cout<<record[x]<<' ';
cout<<endl;
sum++;
}
}
cout<<sum<<endl;
return 0;
}