2016年蓝桥杯C语言大学A组题目7--剪邮票

时间:2022-09-09 21:25:32

第七题:

剪邮票

2016年蓝桥杯C语言大学A组题目7--剪邮票

如【图1.jpg】, 有12张连在一起的12生肖的邮票。

现在你要从中剪下5张来,要求必须是连着的。

(仅仅连接一个角不算相连)

2016年蓝桥杯C语言大学A组题目7--剪邮票

2016年蓝桥杯C语言大学A组题目7--剪邮票

比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。

请你计算,一共有多少种不同的剪取方法。

 请填写表示方案数目的整数。

注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。




从这道题开始蓝桥杯的题目就开始增加难度了,这道题首先第一眼要有DFS算法的感觉,第二点要知道DFS算法的局限性,DFS算法是一直搜索下去无法走回头路的,即所谓的“一笔画”特点。我们观察样例的第二个图发现,这个图形是不能“一笔画”的,所以DFS在这里是无法用来判别连通性的。

因此,想法一:把每一个邮票进行DFS搜索然后除以5来得到正确结果是不可能的!

我们来看一下想法二:用DFS进行深搜,而用BFS来进行宽搜。

首先BFS算法是可以走回头路的,因此我们用BFS来进行联通块的块数判别,如果BFS判别块数为5,则方法+1;



/*
name:Rollchuchy
type:
*/
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int ans=0;
int det=0;
int map[3][4];
int vis[3][4];
int dis[4][2]={
0,1,
0,-1,
1,0,
-1,0
};
struct node{
int x,y;
node(){}
node(int x,int y):x(x),y(y){}
}a[10];

void init()
{
/*int num=1;
for(int i=0;i<3;i++){
for(int j=0;j<4;j++){
map[i][j]=num;
num++;
}
}*/
for(int i=0;i<3;i++){
for(int j=0;j<4;j++){
vis[i][j]=0;
}
}
}

int bfs()
{
int num;
memcpy(map,vis,sizeof(map));
queue<node> que;
que.push(a[0]);
map[a[0].x][a[0].y]=0;
num=1;
while(!que.empty())
{
node start=que.front();que.pop();
for(int i=0;i<4;i++){
int xx=start.x+dis[i][0];
int yy=start.y+dis[i][1];
if(xx>=0&&xx<3&&yy>=0&&yy<4&&map[xx][yy])
{
map[xx][yy]=0;
num++;
que.push(node(xx,yy));
}
}
}
return num;
}

void dfs(int row,int col,int len){
if(len==5){
if(bfs()==5)
ans++;
return ;
}
if(row>=3)return ;
for(int i=col;i<=4;i++){
if(i<4){
vis[row][i]=1;
a[det]=node(row,i);
det++;
dfs(row,i+1,len+1);
det--;
vis[row][i]=0;
}
else {
dfs(row+1,0,len);
}
}
}
int main()
{
init();
dfs(0,0,0);
cout<<ans<<endl;
return 0;
}

2016年蓝桥杯C语言大学A组题目7--剪邮票