Description
Input
. 代表路
* 代表墙
@ 代表CZ的起始位置
^ 代表闺房的出口
A-J 代表带锁的门,对应的钥匙分别为a-j
a-j 代表钥匙,对应的门分别为A-J
每组测试数据之间有一个空行。
Output
Sample Input
4 5 17 @A.B. a*.*. *..*^ c..b* 4 5 16 @A.B. a*.*. *..*^ c..b*
Sample Output
16 -1
思路如下:
用进制转换的方法标记第三维,也就是钥匙的状态,
当前状态的钥匙存储状态,无法保证同一时刻正在进行的另一状态,
有无钥匙,所以说必须是三维数组,同时存储当前第三维所有 该钥匙位置的状态
代码如下:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
const int INF = 1<<10;//将1左移十位
const int N = 22;
const int Size = 999999;
char map[N][N] ;
int vis[N][N][INF];//三维表示状态
struct node
{
int x,y,z,ans ;
}q[Size];//结构体成员变量
int n,m,T;
int mv[4][2] = {{1,0},{0,-1},{-1,0},{0,1}};//定义一个移动数组
void BFS(int x ,int y)
{
int s = 0 , e = 0 ;
node f , t ;
t.x = x ;
t.y = y ;
t.ans = 0 ;
t.z = 0 ;
q[e++] = t ;
vis[t.x][t.y][t.z] = 1;
while(s < e)
{
t = q[s++] ;
if(map[t.x][t.y]=='^' && t.ans < T)//表示找到出口,直接输出步数,返回结果即可
{
printf("%d\n", t.ans);
return ;
}
for(int i = 0;i < 4;i++)//否则循环4个方向进行搜索
{
f.x = t.x + mv[i][0];
f.y = t.y + mv[i][1];
f.z = t.z;
if(f.x >= 0 && f.x < n && f.y >= 0 && f.y < m && vis[f.x][f.y][f.z]==0)
{
if(map[f.x][f.y]=='@' || map[f.x][f.y]=='.' || map[f.x][f.y]=='^')
{
f.ans = t.ans + 1;
q[e++] = f ;
vis[f.x][f.y][f.z] = 1 ;
}
else if('a' <= map[f.x][f.y] && map[f.x][f.y] <='j' )
{
int sum = 0,kk,xx;
f.ans = t.ans + 1;
xx = f.z;
kk = map[f.x][f.y] - 'a' + 1;
for(int ll = 0;ll<kk;ll++)
{
sum = xx % 2;
xx /= 2;
}
if(sum==0)
f.z += pow(2,(map[f.x][f.y]-'a'));
vis[f.x][f.y][f.z] = 1 ;
q[e++] = f ;
}
else if('A' <= map[f.x][f.y] && map[f.x][f.y] <='J' )
{
int sum = 0,kk,xx;
f.ans = t.ans + 1;
xx = f.z;
kk = map[f.x][f.y] - 'A' + 1;
for(int ll = 0;ll<kk;ll++)
{
sum = xx % 2;
xx /= 2;
}
if(sum==1)
{
f.ans = t.ans + 1;
q[e++] = f ;
vis[f.x][f.y][f.z] = 1 ;
}
}
}
}
}
printf("-1\n");
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&T))
{
int x,y;
memset(vis,0,sizeof(vis));//清空数组
for(int i = 0 ; i < n ; i++)
{
scanf("%s%*c", map[i]);
}
for(int i = 0;i<n;i++)
{
for(int j = 0;j < m;j++)
{
if(map[i][j]=='@')
{
x = i;
y = j;
break;
}
}
}
BFS(x,y);
}
return 0;
}
Description
Input
Output
Sample Input
3 3 X#Y *** #*# 3 3 X#Y *#* #*#
Sample Output
4 -1
Hint
思路如下:
分四个方向进行搜索,也可用bfs(广搜)或dfs(深搜)
代码如下:
1.BFS
#include <stdio.h>
#include <string.h>
char Map[16][16];
int mv[16][16];
//mv[i][j] == 0 没有被访问
//mv[i][j] == 1 已经被访问
struct N
{
int x,y,ans;
} q[300];
int jx[] = { 0,-1, 0, 1};
int jy[] = { 1, 0,-1, 0};
void bfs(int x,int y,int n,int m)
{
int s = 0,e = 0;
N t,f;
t.x = x,t.y = y,t.ans = 0;
q[e++] = t;
mv[t.x][t.y] = 1;
while(s < e)
{
t = q[s++];
//printf("x = %d,y = %d,ans = %d\n",t.x,t.y,t.ans);
if(Map[t.x][t.y] == 'Y')
{
printf("%d\n",t.ans);
return ;
}
for(int i = 0; i < 4; ++i)
{
f.x = t.x + jx[i];
f.y = t.y + jy[i];
if(0 <= f.x && f.x < n && 0 <= f.y && f.y < m && mv[f.x][f.y] == 0 && Map[f.x][f.y] != '#')
{
f.ans = t.ans+1;
q[e++] = f;
mv[f.x][f.y] = 1;
}
}
}
printf("-1\n");
return ;
}
int main()
{
int n,m,i,j;
while(scanf("%d %d",&n,&m) != EOF)
{
memset(mv,0,sizeof(mv));
for(i = 0; i < n; ++i)
{
scanf("%*c%s",Map[i]);
}
for(i = 0; i < n; ++i)
{
for(j = 0; j < m; ++j)
{
if(Map[i][j] == 'X')
break;
}
if(j != m)
break;
}
bfs(i,j,n,m);
}
return 0;
}
2.DFS
#include <stdio.h>
#include <string.h>
char Map[16][16];
int mv[16][16];
//mv[i][j] == 0 没有被访问
//mv[i][j] == 1 已经被访问
struct N
{
int x,y,ans;
} q[300];
int jx[] = { 0,-1, 0, 1};
int jy[] = { 1, 0,-1, 0};
int Min;
void dfs(int x,int y,int n,int m,int ans)
{
if(ans >= Min)
{
return ;
}
if(Map[x][y] == 'Y')
{
if(ans < Min)
{
Min = ans;
}
return ;
}
N f;
for(int i = 0; i < 4; ++i)
{
f.x = x + jx[i];
f.y = y + jy[i];
if(0 <= f.x && f.x < n && 0 <= f.y && f.y < m && mv[f.x][f.y] == 0 && Map[f.x][f.y] != '#')
{
mv[f.x][f.y] = 1;
dfs(f.x,f.y,n,m,ans+1);
mv[f.x][f.y] = 0;
}
}
}
int main()
{
int n,m,i,j;
while(scanf("%d %d",&n,&m) != EOF)
{
memset(mv,0,sizeof(mv));
for(i = 0; i < n; ++i)
{
scanf("%*c%s",Map[i]);
}
for(i = 0; i < n; ++i)
{
for(j = 0; j < m; ++j)
{
if(Map[i][j] == 'X')
break;
}
if(j != m)
break;
}
Min = (1<<20);
dfs(i,j,n,m,0);
if(Min == (1<<20))
{
printf("-1\n");
}
else
{
printf("%d\n",Min);
}
}
return 0;
}
Description
Input
Output
Sample Input
3 5 4
Sample Output
6
Hint
思路如下:
题意:给出两个容积分别为 a 和 b 的pot,按照以下三种操作方式,求出能否在一定步数后,使者两个pot的其中一个的水量为c。
思路:bfs求最短路径,与1426类似,只是每个节点的子节点数为6个而已。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int A, B, C;
int vis[105][105];
struct node
{
int a, b, step;
};
void BFS()
{
queue <node> q;
int sa,sb;
node f,t;
f.a = 0; f.b = 0; f.step = 0;
vis[f.a][f.b] = 1;
q.push(f);
while (!q.empty())
{
t = q.front();
q.pop();
if (t.a == C || t.b == C)
{
printf("%d\n",t.step);
return ;
}
for (int i = 1; i <= 6; i++)
{
if (i == 1)
{
sa = A;sb = t.b;
}
else if (i == 2)
{
sa = t.a; sb = B;
}
else if (i == 3)
{
if (t.a + t.b > A)
{sb = t.a + t.b - A;sa = A;}
else
{sb = 0; sa = t.a + t.b;}
}
else if (i == 4)
{
if (t.a + t.b > B)
{sa = t.a + t.b - B; sb = B;}
else
{
sa = 0; sb = t.a + t.b;
}
}
else if (i == 5)
{sa = 0; sb = t.b;}
else
{sa = t.a; sb = 0;}
if (!vis[sa][sb])
{
vis[sa][sb] = 1;
f.a = sa; f.b = sb;
f.step = t.step + 1;
q.push(f);
}
}
}
puts("impossible");
}
int main()
{
while (scanf("%d%d%d", &A, &B, &C) != EOF)
{
memset(vis, 0, sizeof(vis));
BFS();
}
return 0;
}