Description
话说
CZ
由于不守基道,被妖怪抓走了,好基友
WP
在努力讨好高富帅
RQ
救出
CZ
的同时,
CZ
也意识到了自己的错误,然后努力的想逃出妖怪的闺房。
Input
每组测试数据的第一行有三个整数
n,m,t(2<=n,m<=20,t>0)。接下来的
n行
m列为闺房的地图,其中包括
:
. 代表路
* 代表墙
@ 代表CZ的起始位置
^ 代表闺房的出口
A-J 代表带锁的门,对应的钥匙分别为a-j
a-j 代表钥匙,对应的门分别为A-J
. 代表路
* 代表墙
@ 代表CZ的起始位置
^ 代表闺房的出口
A-J 代表带锁的门,对应的钥匙分别为a-j
a-j 代表钥匙,对应的门分别为A-J
每组测试数据之间有一个空行。
Output
针对每组测试数据,如果可以成功逃亡,请输出最少需要多少分钟才能离开,如果不能则输出
-1。
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
X,作为户外运动的忠实爱好者,总是不想呆在家里。现在,他想把死宅Y从家里拉出来。问从X的家到Y的家的最短时间是多少。
Input
多组输入。每组测试数据首先输入两个整数n,m(1<= n ,m<=15 )表示地图大小。接下来的n 行,每行n个字符。保证输入数据合法。
Output
若X可以到达Y的家,输出最少时间,否则输出 -1。
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
You are given two pots, having the volume of A and B liters respectively. The following operations can be performed:
Input
On the first and only line are the numbers A, B, and C. These are all integers in the range from 1 to 100 and C≤max(A,B).
Output
The first line of the output must contain the length of the sequence of operations K. If the desired result can’t be achieved, the first and only line of the file must contain the word ‘impossible’.
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;
}