蓝桥杯第八届(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;
// now = "YYYYWWWWBBBBGGGGRRRROOOO";
mp[now] = 0;
queue<string> Q