[蓝桥杯解题报告]第八届蓝桥杯大赛省赛2017(软件类)真题C++A组 Apare_xzc

蓝桥杯第八届(2017年)省赛软件类C++A组解题报告

Apare_xzc 2020/3/16


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


1. 迷宫(5分)

在这里插入图片描述
在这里插入图片描述

分析:

        按照题意,模拟每个人的路线即可。如果绕圈子,一定出不去。如果走到了之前到过的地方,一定在绕圈子,我们可以开一个标记数组vis[10][10]记录莫个人是否走过该点。

代码:
#include <bits/stdc++.h>
using namespace std;
char a[15][15] = {
   
"UDDLUULRUL",
"UURLLLRRRU",
"RRUURLDLRD",
"RUDDDDUUUU",
"URUDLLRRUU",
"DURLRLDLRL",
"ULLURLLRDU",
"RDLULLRDDD",
"UUDDUDUDLL",
"ULRDLUURRR",
}; 
int ans = 0;
bool vis[15][15];
void solve(int x,int y)
{
   
	int tx = x, ty = y;
	memset(vis,false,sizeof(vis));
	int cnt = 0;
	while(1) {
   
		if(vis[x][y]) return;//说明会死循环,出不去。
		vis[x][y] = true; 
		switch (a[x][y]) {
   
			case 'R':++y;if(y>=10){
   ++ans;cout<<tx<<","<<ty<<endl;return;}break;
			case 'L':--y;if(y<0){
   ++ans;cout<<tx<<","<<ty<<endl;return;}break;
			case 'D':++x;if(x>=10){
   ++ans;cout<<tx<<","<<ty<<endl;return;}break;
			case 'U':--x;if(x<0){
   ++ans;cout<<tx<<","<<ty<<endl;return;}break;			
		}
	}	
} 
int main()
{
   
	for(int i=0;i<10;++i)
		for(int j=0;j<10;++j)
			solve(i,j);
	cout<<ans<<endl;
	return 0;
}

所有能走出去的坐标如下:

0,0
0,4
0,5
0,6
0,7
0,8
0,9
1,0
1,6
1,7
1,8
1,9
6,7
6,8
7,6
7,7
7,8
7,9
8,2
8,3
8,6
8,7
8,8
8,9
9,2
9,3
9,4
9,6
9,7
9,8
9,9
31
------------------------------------------------------------------
Process exited after 0.4011 seconds with return value 0
请按任意键继续. . .

答案为:31

2. 跳蚱蜢(11分)

在这里插入图片描述
在这里插入图片描述

分析:

        我们可以对空盘子编号为0。那么每次蚱蜢跳到空盘子的操作就相当于0号盘子和他相距不大于2的盘子交换。由于编码的好处,我们可以用(x+1)%9,(x-1+9)%9,(x+2)%9,(x-2+9)%9表示可以跳到x盘子的蚱蜢编号。初始状态为012345678,目标状态为087654321,我们bfs即可。

代码:
#include <bits/stdc++.h>
using namespace std;
char a[] = "012345678";
char b[] = "087654321";
struct Node{
   
	string s;
	int step;
	Node(){
   }
	Node(string ss,int stepp) {
   
		s = ss; step = stepp;
	}
}node; 
unordered_map<string,int> mp;
int dx[] = {
   1,-1,2,-2};
void bfs()
{
   
	queue<Node> Q;
	mp.clear();
	node = Node(a,0);
	Q.push(node);
	mp[a] = 1;
	string now,to;
	int step,pos,np;
	while(!Q.empty()) {
   
		node = Q.front(); Q.pop();
		now = node.s, step = node.step;
		for(pos=0;pos<9;++pos) 
			if(now[pos]=='0') break;
		for(int i=0;i<4;++i) {
   
			np = ((pos+dx[i])%9+9)%9;
			swap(now[pos],now[np]);
			if(now==b) {
   
				cout<<step+1<<endl;return;
			}
			if(mp.count(now)) {
   
				swap(now[pos],now[np]);continue;
			}
			Q.push(Node(now,step+1));
			mp[now] = 1;
			swap(now[pos],now[np]);
		}
	}
}
int main()
{
   
	bfs();	
	return 0;
}

在这里插入图片描述

答案:20

3. 魔方状态(13分)

在这里插入图片描述
在这里插入图片描述

分析:

        我们可以对魔方每个面的每个块都编号。上下左右前后按顺时针编号为0,1,2,3…,23。然后我们写几个表示模仿转动的函数R(),U(),F()等。魔方的详细状态表示以及标准转动定义可以参见这里<–
        由于二阶模仿自身的结构,决定了它的性质。它只有8个角块,我们可以让左后方的块不懂,只转动前面,上面,右面。即只进行R,U,F这三个面的操作。
        如果是标准配色的二阶魔方,这样bfs就可以不重不漏地搜到所有的状态。但是本题对魔方重新染了色。左后方的黄绿橙这个块不唯一,所以可能存在两个状态旋转后相等的等价情况。我们可以对魔方旋转后判重。魔方的旋转有x,y,z以及他们的相反方向。然后BFS即可。

代码:
#include <bits/stdc++.h>
using namespace std;
/*
我们对二阶魔方进行编码
上面顺时针:1  2  3  4
下面顺时针:5  6  7  8 
左:        9 10 11 12 
右:       13 14 15 16
前:       17 18 19 20 
后:       21 22 23 24 
*/ 
int tR[3][4] = {
   {
   1,17,5,23},{
   2,18,6,20},{
   15,14,13,12}};
int tU[3][4] = {
   {
   16,12,20,8},{
   17,13,21,9},{
   3,2,1,0}};
int tF[3][4] = {
   {
   2,9,4,15},{
   3,10,5,12},{
   19,18,17,16}};
int tL[3][4] = {
   {
   0,22,4,16},{
   3,21,7,19},{
   11,10,9,8}};
int tD[3][4] = {
   {
   19,11,23,15},{
   18,10,22,14},{
   7,6,5,4}};
int tB[3][4] = {
   {
   1,14,7,8},{
   0,13,6,11},{
   23,22,21,20}};
string R(string);
string R_(string);
string U(string);
string U_(string);
string F (string);
string F_(string);
string D (string);
string D_(string);
string L (string);
string L_(string);
string B (string);
string B_(string);
string x (string);
string y (string);
string z (string);
unordered_map<string,int> mp;
bool check(string);
void bfs() {
   
	string now = "YYYYOOOOGGGGGGGGOOOOYYYY",to;<
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值