2016蓝桥杯省赛C/C++B组7题剪邮票 for循环暴力+bfs判断联通

剪邮票


如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。

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

2016蓝桥杯省赛C/C++B组7题剪邮票 for循环暴力+bfs判断联通_第1张图片2016蓝桥杯省赛C/C++B组7题剪邮票 for循环暴力+bfs判断联通_第2张图片2016蓝桥杯省赛C/C++B组7题剪邮票 for循环暴力+bfs判断联通_第3张图片


思路:

    没错,一开始我傻到写了个暴搜,天真的以为每个重复了五次,除以5即可...mmp,后来才想起来....

    因为每个位置每次所走的方向不一样也会导致同一个解,这就导致每一个重复次数不确定,所以GG。

    因为只需找五个,而且还是填空题,我们可以五层for找到五个点(当然暴搜好像更方便代码更简洁啊),BFS判断一下五个点是否联通即可(这里因为想找到所有情况一下子判断有点难,干脆搜索吧)


最后答案116


#include 

using namespace std;

int a[10];
int Go[4][2] = {0,1,1,0,0,-1,-1,0};
bool check()
{
	int book[30];
	memset(book,0,sizeof book);
	for(int i = 1;i <= 5;++i)
		book[a[i]] = 1;
	queueQ;
	while(!Q.empty()) Q.pop();
	bool vis[30];
	memset(vis,0,sizeof vis);
	vis[a[1]] = 1;
	Q.push(a[1]);
	while(!Q.empty())
	{
		int cur = Q.front();Q.pop();
		int x = (cur-1) /4;int y = (cur - 1)% 4;
		for(int i = 0;i < 4;++i)
		{

			int tx = x + Go[i][0];
			int ty = y + Go[i][1];
			int nxt = tx * 4 + ty + 1;
			if(tx >= 0 && tx < 3 && ty >= 0 && ty < 4 && !vis[nxt] && book[nxt])
			{
				vis[nxt] = 1;
				Q.push(nxt);
			}
		}
	}
	for(int i = 1;i <= 5;++i)
		if(vis[a[i]] == 0)
			return 0;
	return 1;
}
int main()
{
	int ans = 0;
	for(int i = 1;i <= 12;++i)
	{
		a[1] = i;
		for(int j = i + 1;j <= 12;++j)
		{
			a[2] = j;
			for(int k = j + 1;k <= 12;++k)
			{
				a[3] = k;
				for(int l = k + 1;l <= 12;++l)
				{
					a[4] = l;
					for(int g = l + 1;g <= 12;++g)
					{
						a[5] = g;
						 if(check())
						 ans++;
					}
				}
			}
		}
	}
	printf("%d\n",ans);
	return 0;
}

你可能感兴趣的:(2016蓝桥杯省赛C/C++B组7题剪邮票 for循环暴力+bfs判断联通)