A - 数据结构实验之图论一:基于邻接矩阵的广度优先搜索遍历
Description
给定一个无向连通图,顶点编号从0到n-1,用广度优先搜索(BFS)遍历,输出从某个顶点出发的遍历序列。(同一个结点的同层邻接点,节点编号小的优先遍历)
Input
输入第一行为整数n(0< n <100),表示数据的组数。
对于每组数据,第一行是三个整数k,m,t(0<k<100,0<m<(k-1)*k/2,0< t<k),表示有m条边,k个顶点,t为遍历的起始顶点。
下面的m行,每行是空格隔开的两个整数u,v,表示一条连接u,v顶点的无向边。
Output
输出有n行,对应n组输出,每行为用空格隔开的k个整数,对应一组数据,表示BFS的遍历结果。
Sample
Input
1
6 7 0
0 3
0 4
1 4
1 5
2 3
2 4
3 5
Output
0 3 4 2 5 1
Hint
以邻接矩阵作为存储结构。
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1010;
int dis[N];
int vis[N][N];
int n,m,s;
int ch[N];
int top=0;
void bfs(int s)
{
int in,out;
in=out=0;
ch[in++]=s;
dis[s]=1;
while(in>out)
{
int u=ch[out];
for(int i=0;i<n;i++)
{
if(dis[i]==0&&vis[u][i]==1)
{
ch[in++]=i;
dis[i]=1;
}
}
out++;
}
for(int i=0;i<in;i++)
{
if(i==in-1)
{
printf("%d\n",ch[i]);
}
else
{
printf("%d ",ch[i]);
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d %d %d",&n,&m,&s);
memset(dis,0,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(ch,0,sizeof(ch));
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d %d",&u,&v);
vis[u][v]=vis[v][u]=1;
}
bfs(s);
}
return 0;
}
B - 数据结构实验之图论二:图的深度遍历
Description
请定一个无向图,顶点编号从0到n-1,用深度优先搜索(DFS),遍历并输出。遍历时,先遍历节点编号小的。
Input
输入第一行为整数n(0 < n < 100),表示数据的组数。 对于每组数据,第一行是两个整数k,m(0 < k < 100,0 < m < k*k),表示有m条边,k个顶点。 下面的m行,每行是空格隔开的两个整数u,v,表示一条连接u,v顶点的无向边。
Output
输出有n行,对应n组输出,每行为用空格隔开的k个整数,对应一组数据,表示DFS的遍历结果。
Sample
Input
1
4 4
0 1
0 2
0 3
2 3
Output
0 1 2 3
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1010;
int dis[N];
int vis[N][N];
int n,m,s;
int ch[N];
int top=0;
void dfs(int s)
{
dis[s]=1;
ch[top++]=s;
for(int i=0;i<n;i++)
{
if(dis[i]==0&&vis[s][i]==1)
{
dfs(i);
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&n,&m);
memset(dis,0,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(ch,0,sizeof(ch));
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d %d",&u,&v);
vis[u][v]=vis[v][u]=1;
}
top=0;
dfs(0);
for(int i=0;i<top;i++)
{
if(i==top-1)
{
printf("%d\n",ch[i]);
}
else
{
printf("%d ",ch[i]);
}
}
}
return 0;
}
C - 数据结构实验之图论三:判断可达性
Description
在古老的魔兽传说中,有两个军团,一个叫天灾,一个叫近卫。在他们所在的地域,有n个隘口,编号为1..n,某些隘口之间是有通道连接的。其中近卫军团在1号隘口,天灾军团在n号隘口。某一天,天灾军团的领袖巫妖王决定派兵攻打近卫军团,天灾军团的部队如此庞大,甚至可以填江过河。但是巫妖王不想付出不必要的代价,他想知道在不修建任何通道的前提下,部队是否可以通过隘口及其相关通道到达近卫军团展开攻击。由于n的值比较大(n<=1000),于是巫妖王找到了擅长编程的你 =_=,请你帮他解决这个问题,否则就把你吃掉变成他的魔法。为了拯救自己,赶紧想办法吧。
Input
输入包含多组,每组格式如下。
第一行包含两个整数n,m(分别代表n个隘口,这些隘口之间有m个通道)。
下面m行每行包含两个整数a,b;表示从a出发有一条通道到达b隘口(注意:通道是单向的)。
Output
如果天灾军团可以不修建任何通道就到达1号隘口,那么输出YES,否则输出NO。
Sample
Input
2 1
1 2
2 1
2 1
Output
NO
YES
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1010;
int dis[N];
int vis[N][N];
int n,m,s;
int ch[N];
int top=0;
void dfs(int s)
{
dis[s]=1;
for(int i=0;i<n;i++)
{
if(dis[i]==0&&vis[s][i]==1)
{
dfs(i);
}
}
}
int main()
{
int t;
while(~scanf("%d %d",&n,&m))
{
memset(dis,0,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(ch,0,sizeof(ch));
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d %d",&u,&v);
vis[u][v]=1;
}
top=0;
dfs(n);
if(dis[1]==1)
{
printf("YES\n");
}
else
{
printf("NO\n");
}
}
return 0;
}
D - 数据结构实验之图论四:迷宫探索
Description
有一个地下迷宫,它的通道都是直的,而通道所有交叉点(包括通道的端点)上都有一盏灯和一个开关;请问如何从某个起点开始在迷宫中点亮所有的灯并回到起点?
Input
连续T组数据输入,每组数据第一行给出三个正整数,分别表示地下迷宫的结点数N(1 < N <= 1000)、边数M(M <= 3000)和起始结点编号S,随后M行对应M条边,每行给出一对正整数,表示一条边相关联的两个顶点的编号。
Output
若可以点亮所有结点的灯,则输出从S开始并以S结束的序列,序列中相邻的顶点一定有边,否则只输出部分点亮的灯的结点序列,最后输出0,表示此迷宫不是连通图。
访问顶点时约定以编号小的结点优先的次序访问,点亮所有可以点亮的灯后,以原路返回的方式回到起点。
Sample
Input
1
6 8 1
1 2
2 3
3 4
4 5
5 6
6 4
3 6
1 5
Output
1 2 3 4 5 6 5 4 3 2 1
Hint
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1010;
int dis[N];
int vis[N][N];
int n,m,s;
int ch[N];
int top=0;
void dfs(int s)
{
dis[s]=1;
ch[top++]=s;
for(int i=1;i<=n;i++)
{
if(dis[i]==0&&vis[s][i]==1)
{
dis[i]=1;
dfs(i);
ch[top++]=s;
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d %d %d",&n,&m,&s);
memset(dis,0,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(ch,0,sizeof(ch));
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d %d",&u,&v);
vis[u][v]=vis[v][u]=1;
}
top=0;
dfs(s);
for(int i=0;i<top;i++)
{
if(i==top-1)
{
printf("%d",ch[i]);
}
else
{
printf("%d ",ch[i]);
}
}
if(top!=2*n-1)
{
printf(" 0\n");
}
else
{
printf("\n");
}
}
return 0;
}
E - 数据结构实验之图论五:从起始点到目标点的最短步数(BFS)
Description
在古老的魔兽传说中,有两个军团,一个叫天灾,一个叫近卫。在他们所在的地域,有n个隘口,编号为1..n,某些隘口之间是有通道连接的。其中近卫军团在1号隘口,天灾军团在n号隘口。某一天,天灾军团的领袖巫妖王决定派兵攻打近卫军团,天灾军团的部队如此庞大,甚至可以填江过河。但是巫妖王不想付出不必要的代价,他想知道在不修建任何通道的前提下,部队是否可以通过隘口及其相关通道到达近卫军团展开攻击;如果可以的话,最少需要经过多少通道。由于n的值比较大(n<=1000),于是巫妖王找到了擅长编程的你 =_=,请你帮他解决这个问题,否则就把你吃掉变成他的魔法。为了拯救自己,赶紧想办法吧。
Input
输入包含多组,每组格式如下。
第一行包含两个整数n,m(分别代表n个隘口,这些隘口之间有m个通道)。
下面m行每行包含两个整数a,b;表示从a出发有一条通道到达b隘口(注意:通道是单向的)。
Output
如果天灾军团可以不修建任何通道就到达1号隘口,那么输出最少经过多少通道,否则输出NO。
Sample
Input
2 1
1 2
2 1
2 1
Output
NO
1
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1010;
int dis[N];
int vis[N][N];
int n,m,s;
int ch[N];
int top=0;
struct node
{
int data,step;
} e[N];
void bfs(int s)
{
int in,out;
in=out=0;
e[in].data=s;
e[in].step=0;
in++;
dis[s]=1;
while(in>out)
{
int u=e[out].data;
if(u==1)
{
break;
}
for(int i=1; i<=n; i++)
{
if(dis[i]==0&&vis[u][i]==1)
{
dis[i]=1;
e[in].data=i;
e[in].step=e[out].step+1;
in++;
}
}
out++;
}
if(in==out)
{
printf("NO\n");
}
else
{
printf("%d\n",e[out].step);
}
}
int main()
{
while(~scanf("%d %d",&n,&m))
{
memset(dis,0,sizeof(dis));
memset(vis,0,sizeof(vis));
for(int i=0; i<m; i++)
{
int u,v;
scanf("%d %d",&u,&v);
vis[u][v]=1;
}
bfs(n);
}
return 0;
}
F - 数据结构实验之图论六:村村通公路
Description
当前农村公路建设正如火如荼的展开,某乡镇政府决定实现村村通公路,工程师现有各个村落之间的原始道路统计数据表,表中列出了各村之间可以建设公路的若干条道路的成本,你的任务是根据给出的数据表,求使得每个村都有公路连通所需要的最低成本。
Input
连续多组数据输入,每组数据包括村落数目N(N <= 1000)和可供选择的道路数目M(M <= 3000),随后M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个村庄的编号和修建该道路的预算成本,村庄从1~N编号。
Output
输出使每个村庄都有公路连通所需要的最低成本,如果输入数据不能使所有村庄畅通,则输出-1,表示有些村庄之间没有路连通。
Sample
Input
5 8
1 2 12
1 3 9
1 4 11
1 5 3
2 3 6
2 4 9
3 4 4
4 5 6
Output
19
Hint
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=101010;
struct node
{
int u,v,w;
} e[N];
int f[N];
int m,n;
bool cmp(node x,node y)
{
return x.w<y.w;
}
void init(int n)
{
for(int i=0; i<=n; i++)
{
f[i]=i;
}
}
int find1(int x)
{
if(x!=f[x])
{
return f[x]=find1(f[x]);
}
else
{
return x;
}
}
bool join(int x,int y)
{
int fx=find1(x);
int fy=find1(y);
if(fx!=fy)
{
f[fx]=fy;
return false;
}
else
{
return true;
}
}
int main()
{
while(~scanf("%d %d",&n,&m))
{
init(n);
for(int i=0; i<m; i++)
{
cin>>e[i].u>>e[i].v>>e[i].w;
}
sort(e,e+m,cmp);
int ans=0;
int cnt=0;
for(int i=0; i<m; i++)
{
if(!join(e[i].u,e[i].v))
{
ans+=e[i].w;
cnt++;
}
}
if(cnt==n-1)
{
printf("%d\n",ans);
}
else
{
printf("-1\n");
}
}
return 0;
}
G - 数据结构实验之图论七:驴友计划
Description
做为一个资深驴友,小新有一张珍藏的自驾游线路图,图上详细的标注了全国各个城市之间的高速公路距离和公路收费情况,现在请你编写一个程序,找出一条出发地到目的地之间的最短路径,如果有多条路径最短,则输出过路费最少的一条路径。
Input
连续T组数据输入,每组输入数据的第一行给出四个正整数N,M,s,d,其中N(2 <= N <= 500)是城市数目,城市编号从0~N-1,M是城市间高速公路的条数,s是出发地的城市编号,d是目的地的城市编号;随后M行,每行给出一条高速公路的信息,表示城市1、城市2、高速公路长度、收费额,中间以空格间隔,数字均为整数且不超过500,输入数据均保证有解。
Output
在同一行中输出路径长度和收费总额,数据间用空格间隔。
Sample
Input
1
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
Output
3 40
Hint
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1010;
int dis[N];
int vis[N][N];
int cis[N][N];
int n,m,s,d;
int ch[N];
int top=0;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d %d %d %d",&n,&m,&s,&d);
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
vis[i][j]=cis[i][j]=inf;
}
}
for(int i=0;i<m;i++)
{
int u,v,w,cost;
scanf("%d %d %d %d",&u,&v,&w,&cost);
vis[u][v]=vis[v][u]=min(w,vis[u][v]);
cis[u][v]=cis[v][u]=min(cost,cis[u][v]);
}
for(int k=0;k<n;k++)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(vis[i][j]>vis[i][k]+vis[k][j])
{
vis[i][j]=vis[i][k]+vis[k][j];
cis[i][j]=cis[i][k]+cis[k][j];
}
else if(vis[i][j]==vis[i][k]+vis[k][j]&&cis[i][j]>cis[i][k]+cis[k][j])
{
cis[i][j]=cis[i][k]+cis[k][j];
}
}
}
}
printf("%d %d\n",vis[s][d],cis[s][d]);
}
return 0;
}
H - 数据结构实验之图论八:欧拉回路
Description
在哥尼斯堡的一个公园里,有七座桥将普雷格尔河中两个岛及岛与河岸连接起来。
能否走过这样的七座桥,并且每桥只走一次?瑞士数学家欧拉最终解决了这个问题并由此创立了拓扑学。欧拉通过对七桥问题的研究,不仅圆满地回答了哥尼斯堡七桥问题,并证明了更为广泛的有关一笔画的三条结论,人们通常称之为欧拉定理。对于一个连通图,通常把从某结点出发一笔画成所经过的路线叫做欧拉路。人们又通常把一笔画成回到出发点的欧拉路叫做欧拉回路。具有欧拉回路的图叫做欧拉图。
你的任务是:对于给定的一组无向图数据,判断其是否成其为欧拉图?
Input
连续T组数据输入,每组数据第一行给出两个正整数,分别表示结点数目N(1 < N <= 1000)和边数M;随后M行对应M条边,每行给出两个正整数,分别表示该边连通的两个结点的编号,结点从1~N编号。
Output
若为欧拉图输出1,否则输出0。
Sample
Input
1
6 10
1 2
2 3
3 1
4 5
5 6
6 4
1 4
1 6
3 4
3 6
Output
1
Hint
如果无向图连通并且所有结点的度都是偶数,则存在欧拉回路,否则不存在。
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1010;
int dis[N];
int vis[N][N];
int m,n,s;
int ch[N];
int dp[N];
int top;
void dfs(int s)
{
dis[s]=1;
top++;
for(int i=1;i<=n;i++)
{
if(!dis[i]&&vis[s][i]==1)
{
dis[i]=1;
dfs(i);
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&n,&m);
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis));
memset(dp,0,sizeof(dp));
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d %d",&u,&v);
vis[u][v]=vis[v][u]=1;
dp[u]++;
dp[v]++;
}
top=0;
dfs(1);
int flag=0;
for(int i=1;i<=n;i++)
{
if(dp[i]%2)
{
flag=1;
break;
}
}
if(flag==0&&top==n)
{
printf("1\n");
}
else
{
printf("0\n");
}
}
return 0;
}
I - 数据结构实验之图论九:最小生成树
Description
有n个城市,其中有些城市之间可以修建公路,修建不同的公路费用是不同的。现在我们想知道,最少花多少钱修公路可以将所有的城市连在一起,使在任意一城市出发,可以到达其他任意的城市。
Input
输入包含多组数据,格式如下。
第一行包括两个整数n m,代表城市个数和可以修建的公路个数。(n <= 100, m <=10000)
剩下m行每行3个非负整数a b c,代表城市a 和城市b之间可以修建一条公路,代价为c(城市编号从1到n)。
Output
每组输出占一行,仅输出最小花费。
Sample
Input
3 2
1 2 1
1 3 1
1 0
Output
2
0
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=101010;
struct node
{
int u,v,w;
} e[N];
int f[N];
int m,n;
bool cmp(node x,node y)
{
return x.w<y.w;
}
void init(int n)
{
for(int i=0; i<=n; i++)
{
f[i]=i;
}
}
int find1(int x)
{
if(x!=f[x])
{
return f[x]=find1(f[x]);
}
else
{
return x;
}
}
bool join(int x,int y)
{
int fx=find1(x);
int fy=find1(y);
if(fx!=fy)
{
f[fx]=fy;
return false;
}
else
{
return true;
}
}
int main()
{
while(~scanf("%d %d",&n,&m))
{
init(n);
for(int i=0; i<m; i++)
{
cin>>e[i].u>>e[i].v>>e[i].w;
}
sort(e,e+m,cmp);
int ans=0;
int cnt=0;
for(int i=0; i<m; i++)
{
if(!join(e[i].u,e[i].v))
{
ans+=e[i].w;
cnt++;
}
}
printf("%d\n",ans);
}
return 0;
}
J - 数据结构实验之图论十:判断给定图是否存在合法拓扑序列
Description
给定一个有向图,判断该有向图是否存在一个合法的拓扑序列。
Input
输入包含多组,每组格式如下。
第一行包含两个整数n,m,分别代表该有向图的顶点数和边数。(n<=10)
后面m行每行两个整数a b,表示从a到b有一条有向边。
Output
若给定有向图存在合法拓扑序列,则输出YES;否则输出NO。
Sample
Input
1 0
2 2
1 2
2 1
Output
YES
NO
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1010;
int G[N][N];//图;
int dis[N];//入度;
int n;
queue<int>q;
void Tsort()
{
for(int i=1; i<=n; i++)
{
if(!dis[i])//把入度为零的全部加入到队列中;
{
q.push(i);
}
}
int cnt=0;
while(!q.empty())
{
int u=q.front();
q.pop();
cnt++;
for(int i=1; i<=n; i++)
{
if(G[u][i]==1)
{
int v=i;//v是要服从于u的事件。
if(dis[v])//如果v的入度不为零
dis[v]--;
if(dis[v]==0)//如果v的入度为零;
q.push(v);//加入队列中;
}
}
}
if(cnt==n)
printf("YES\n");
else
printf("NO\n");
}
int main()
{
int m;
while(~scanf("%d %d",&n,&m))
{
int a,b;
memset(dis,0,sizeof(dis));
memset(G,0,sizeof(G));
for(int i=0; i<m; i++)
{
scanf("%d %d",&a,&b);
G[b][a]=1;;
dis[a]++;
}
Tsort();
}
return 0;
}
K - 老鼠走迷宫
Description
现在一只老鼠被困在了迷宫里!你需要判断老鼠能否走出迷宫。
老鼠只能向上下左右四个方向移动。我们认为只要老鼠走到了迷宫的边界即算走出迷宫。
Input
第一行输入两个整数 nnn, mmm (1⩽n,m⩽100)(1 \leqslant n, m \leqslant 100)(1⩽n,m⩽100) 表示迷宫地图的尺寸。
接下来输入 nnn 行,每行 mmm 个字符,表示迷宫地图。其中 M
表示老鼠的位置,*
代表墙壁,.
代表空地。
Output
如果老鼠可以走出迷宫,则输出一行 Yes
,否则输出一行 No
。
Sample
Input
4 4
*.**
*..*
*.M*
****
Output
Yes
Hint
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int dis[3010][3010];
int vis[3030][3030];
int v[1010];
int m,n;
int inf=0x3f3f3f3f;
int flag=0;
int dx[]= {-1,1,0,0};
int dy[]= {0,0,-1,1};
void dfs(int x,int y)
{
dis[x][y]=1;
if(x==0||y==0||x==n-1||y==m-1)
{
flag=1;
return;
}
for(int i=0;i<4;i++)
{
int xx=x+dx[i];
int yy=y+dy[i];
if(vis[xx][yy]==1&&dis[xx][yy]==0&&xx>=0&&xx<n&&yy>=0&&yy<m)
{
dfs(xx,yy);
}
}
}
int main()
{
scanf("%d %d",&n,&m);
int i,j;
char s;
int x,y;
for(i=0;i<n;i++)
{
getchar();
for(j=0;j<m;j++)
{
scanf("%c",&s);
if(s=='*')
{
vis[i][j]=0;
}
else if(s=='.')
{
vis[i][j]=1;
}
else
{
vis[i][j]=1;
x=i;
y=j;
}
}
}
flag=0;
memset(dis,0,sizeof(dis));
dfs(x,y);
if(flag==0)
{
printf("No\n");
}
else
{
printf("Yes\n");
}
return 0;
}
L - 病毒扩散
Description
2019-ncov的突然出现扰乱了人们的日常生活,它具有极强的传染性,可以快速的在人群中扩散,现在研究人员正在模拟其在人群中的扩散情况.
在一个n*m矩阵所示的人群中,*为普通人,#为佩戴口罩的人,@为病毒携带者,已知每秒每位病毒携带者会将病毒传染给相邻八个方向的未戴口罩的普通人。请问 x 秒后会有多少名传染者(初始为第0秒)?
Input
第一行输入空格分隔的三个数n,m,x代表n行,m列的空间,x秒(n,m<=1000)。
接下来n行每行m人如上述所示。
Output
一个数字,代表最终被传染的人数。
Sample
Input
4 4 2
****
*@**
**##
**#*
Output
12
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int dis[3010][3010];
int vis[3030][3030];
int m,n;
int inf=0x3f3f3f3f;
int flag=0;
int dx[]= {-1,1,0,0,1,1,-1,-1};
int dy[]= {0,0,-1,1,1,-1,1,-1};
int in,out;
struct node
{
int x,y;
}v[1001000];
void bfs(int x,int y)
{
for(int i=0;i<8;i++)
{
int xx=x+dx[i];
int yy=y+dy[i];
if(vis[xx][yy]==1&&dis[xx][yy]==0&&xx>=0&&xx<n&&yy>=0&&yy<m)
{
dis[xx][yy]=1;
v[in].x=xx;
v[in].y=yy;
in++;
}
}
}
int main()
{
int k;
scanf("%d %d %d",&n,&m,&k);
int i,j;
char s;
int x,y;
in=out=0;
memset(dis,0,sizeof(dis));
for(i=0;i<n;i++)
{
getchar();
for(j=0;j<m;j++)
{
scanf("%c",&s);
if(s=='#')
{
vis[i][j]=0;
}
else if(s=='*')
{
vis[i][j]=1;
}
else
{
vis[i][j]=1;
dis[i][j]=1;
v[in].x=i;
v[in].y=j;
in++;
}
}
}
for(i=0;i<k;i++)
{
int DD=in;
while(out<DD)
{
bfs(v[out].x,v[out].y);
out++;
}
}
printf("%d\n",in);
return 0;
}
M - 魔戒
Description
蓝色空间号和万有引力号进入了四维水洼,发现了四维物体--魔戒。
这里我们把飞船和魔戒都抽象为四维空间中的一个点,分别标为 "S" 和 "E"。空间中可能存在障碍物,标为 "#",其他为可以通过的位置。
现在他们想要尽快到达魔戒进行探索,你能帮他们算出最小时间是最少吗?我们认为飞船每秒只能沿某个坐标轴方向移动一个单位,且不能越出四维空间。
Input
输入数据有多组(数据组数不超过 30),到 EOF 结束。
每组输入 4 个数 x, y, z, w 代表四维空间的尺寸(1 <= x, y, z, w <= 30)。
接下来的空间地图输入按照 x, y, z, w 轴的顺序依次给出,你只要按照下面的坐标关系循环读入即可。
for 0, x-1
for 0, y-1
for 0, z-1
for 0, w-1
保证 "S" 和 "E" 唯一。
Output
对于每组数据,输出一行,到达魔戒所需的最短时间。
如果无法到达,输出 "WTF"(不包括引号)。
Sample
Input
2 2 2 2
..
.S
..
#.
#.
.E
.#
..
2 2 2 2
..
.S
#.
##
E.
.#
#.
..
Output
1
3
#include <iostream>
#include<bits/stdc++.h>
#define ll long long
const int N = 35;
using namespace std;
int A,B,C,D;
char mp[55][55][55][55];
bool vis[55][55][55][55];
int dirx[]= {0,0,0,0,0,0,1,-1};
int diry[]= {0,0,0,0,1,-1,0,0};
int dirz[]= {0,0,1,-1,0,0,0,0};
int dirw[]= {1,-1,0,0,0,0,0,0};
int flag;
int aa,bb,cc,dd;
struct node
{
int x;
int y;
int z;
int w;
int sum;
};
int judge(int x,int y,int z,int w)
{
if (x>=0&&x<A&&y>=0&&y<B&&z>=0&&z<C&&w>=0&&w<D&&vis[x][y][z][w]==0&&mp[x][y][z][w]!='#')
return 1;
return 0;
}
void bfs(int aa,int bb,int cc,int dd)
{
queue<node>Q;
node a;
a.x=aa;
a.y=bb;
a.z=cc;
a.w=dd;
a.sum=0;
vis[aa][bb][cc][dd]=1;
Q.push(a);
flag=1;
while (!Q.empty())
{
a=Q.front();
Q.pop();
if (mp[a.x][a.y][a.z][a.w]=='E')
{
printf ("%d\n",a.sum);
flag=0;
break;
}
for (int i=0; i<8; i++)
{
node b;
b=a;
b.x+=dirx[i];
b.y+=diry[i];
b.z+=dirz[i];
b.w+=dirw[i];
if (judge(b.x,b.y,b.z,b.w))
{
b.sum++;
vis[b.x][b.y][b.z][b.w]=1;
Q.push(b);
}
}
}
if (flag)
printf ("WTF\n");
}
int main ()
{
while(cin>>A>>B>>C>>D)
{
getchar();
for (int i=0; i<A; i++)
{
for (int j=0; j<B; j++)
{
for (int k=0; k<C; k++)
{
for(int l=0; l<D; l++)
{
cin>>mp[i][j][k][l];
if (mp[i][j][k][l]=='S')
{
aa=i;
bb=j;
cc=k;
dd=l;
}
}
getchar();
}
}
}
memset(vis,0,sizeof(vis));
bfs(aa,bb,cc,dd);
}
return 0;
}
N - New Game
Description
New game是在一个M*M的特殊棋盘(棋盘的第i行都标上了数字i)上进行的新式游戏。给定一个数字N,要求选手把一个棋子从左上角(1,1)移到右下角(M,M),移动时只能往右或往下。要求移动后经过的数字和为N,且拐弯的次数最少。
如果对给出的N,选手不能找出移动方案使得经过的数字和为N或找出的路径拐弯次数不是最少,选手就输了。所以,选手一定千方百计要找出满足条件的路径!!
Input
两个正整数M,N(其中M<=16),数据保证有解。
Output
最少拐弯数。
Sample
Input
4 22
Output
1
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int n,m;
int max1=INT_MAX;
int flag1=0;
void dfs(int x,int y,int sum,int num,int flag)
{
if(x==m&&y==m&&sum==n)
{
max1=min(max1,num);
return;
}
if(sum>n||x>m||y>m)
{
return;
}
if(flag==0)
{
dfs(x+1,y,sum+x+1,num,1);
dfs(x,y+1,sum+x,num,-1);
}
else if(flag==1)
{
dfs(x+1,y,sum+x+1,num,1);
dfs(x,y+1,sum+x,num+1,-1);
}
else
{
dfs(x+1,y,sum+x+1,num+1,1);
dfs(x,y+1,sum+x,num,-1);
}
return;
}
int main()
{
scanf("%d %d",&m,&n);
dfs(1,1,1,0,0);
printf("%d\n",max1);
return 0;
}