纪中集训 Day39&Day40
T1:
广搜
T2:
n
n
n遍广搜
T3:
看不懂,蒙分
T1
题目:
农场上起火了,奶牛们正在紧急赶去灭火!
农场可以用一个像这样的10×10的字符方阵来描述:
字符’
B
B
B‘表示正着火的牛棚。字符’
L
L
L‘表示一个湖,而字符’
R
R
R‘表示农场上的一块巨大岩石。奶牛们想要沿着一条湖到牛棚之间的路径组成一条“水桶传递队列”,这样她们就可以沿着这条路径传递水桶来帮助灭火。当两头奶牛在东南西北四个方向上相邻时水桶可以在她们之间传递。这对于湖边的奶牛也是对的——奶牛只能在紧挨着湖的时候才能用水桶从湖里取水。类似地,奶牛只能在紧挨着牛棚的时候才能用水去灭牛棚的火。
请帮助求出奶牛们为了组成这样的“水桶传递队列”需要占据的’.'格子的最小数量。奶牛不能站在岩石所在的方格之内,此外保证牛棚和湖不是相邻的。
输入:
输入包含10行,每行10个字符,描述这个农场的布局。输入保证图案中恰有一个字符’
B
B
B’、一个字符’
L
L
L‘以及一个字符’
R
R
R’。
输出:
输出一个整数,为组成一条可行的水桶传递队列所需要的奶牛的最小数量。
样例:
input
…
…
…
…B…
…
…R…
…
…
…L…
…
output
7
提示:
在这个例子中,以下是其中一个可行的方案,使用了最小数量的奶牛(7):
…
…
…
…B…
…C…
…CC.R…
…CCC…
…C…
…L…
…
解题思路:
广搜模板题
代码:
#include<iostream>
#include<cstdio>
using namespace std;
struct hhx{
int x,y;
}f[110];
int fx[5]={0,0,0,1,-1},fy[5]={0,1,-1,0,0};
int xx,yy,t,h,xz,yz,x,y;
int a[12][12],b[12][12];
char c;
int main()
{
freopen("buckets.in","r",stdin);
freopen("buckets.out","w",stdout);
for (int i=1;i<=10;i++) //输入,改造迷宫
{
for (int j=1;j<=10;j++)
{
scanf("%c",&c);
if (c=='.')
a[i][j]=0;
else if (c=='B')
{
a[i][j]=0;
xz=i;
yz=j;
}
else if (c=='L')
{
a[i][j]=1;
x=i;
y=j;
}
else a[i][j]=1;
}
scanf("%c",&c);
}
f[1].x=x;
f[1].y=y;
t=1;
do {
h++;
for (int i=1;i<=4;i++)
{
xx=f[h].x+fx[i];
yy=f[h].y+fy[i];
if (a[xx][yy]==0&&xx<=10&&yy<=10&&xx>0&&yy>0)
{
a[xx][yy]++; //标记走过
b[xx][yy]=b[f[h].x][f[h].y]+1; //求路径
t++;
f[t].x=xx;
f[t].y=yy; //进队列
if (xx==xz&&yy==yz) //到底终点
{
cout<<b[xx][yy]-1<<endl;
h=t;
break;
}
}
}
}while (h<t);
fclose(stdin);
fclose(stdout);
return 0;
}
T2
题目:
牛奶生意正红红火火!
F
a
r
m
e
r
Farmer
Farmer
J
o
h
n
John
John的牛奶加工厂内有N个加工站,编号为1…
N
N
N(1≤
N
N
N≤100),以及
N
N
N−1条通道,每条连接某两个加工站。(通道建设很昂贵,所以
F
a
r
m
e
r
Farmer
Farmer
J
o
h
n
John
John选择使用了最小数量的通道,使得从每个加工站出发都可以到达所有其他加工站)。
为了创新和提升效率,
F
a
r
m
e
r
Farmer
Farmer
J
o
h
n
John
John在每条通道上安装了传送带。不幸的是,当他意识到传送带是单向的已经太晚了,现在每条通道只能沿着一个方向通行了!所以现在的情况不再是从每个加工站出发都能够到达其他加工站了。
然而,
F
a
r
m
e
r
Farmer
Farmer
J
o
h
n
John
John认为事情可能还不算完全失败,只要至少还存在一个加工站i满足从其他每个加工站出发都可以到达加工站
i
i
i。注意从其他任意一个加工站
j
j
j前往加工站
i
i
i可能会经过
i
i
i和
j
j
j之间的一些中间站点。请帮助
F
a
r
m
e
r
Farmer
Farmer
J
o
h
n
John
John求出是否存在这样的加工站
i
i
i。
输入:
输入的第一行包含一个整数
N
N
N,为加工站的数量。以下
N
N
N−1行每行包含两个空格分隔的整数
a
i
ai
ai和
b
i
bi
bi,满足1≤
a
i
ai
ai,
b
i
bi
bi≤
N
N
N以及
a
i
ai
ai≠
b
i
bi
bi。这表示有一条从加工站
a
i
ai
ai向加工站
b
i
4
移
动
的
传
送
带
,
仅
允
许
沿
从
bi4移动的传送带,仅允许沿从
bi4移动的传送带,仅允许沿从ai
到
到
到bi$的方向移动。
输出:
如果存在加工站i满足可以从任意其他加工站出发都可以到达加工站
i
i
i,输出最小的满足条件的
i
i
i。否则,输出−1。
样例:
input
3
1 2
3 2
output
2
解题思路:
n
n
n遍广搜
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int x,y,n,t,p[120],f[120],head[120];
struct hhx{
int to,next;
}m[120];
void add(int x,int y)
{
m[++t].to=y;
m[t].next=head[x];
head[x]=t;
}
int main()
{
freopen("factory.in","r",stdin);
freopen("factory.out","w",stdout)
scanf("%d",&n);
for (int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
add(y,x);
}
for (int i=1;i<=n;i++)
{
memset(p,0,sizeof(p));
memset(f,0,sizeof(f));
int h=0,t=1,ans=n-1;
f[1]=i;
p[i]=1;
do{
h++;
for (int j=head[f[h]];j;j=m[j].next)
{
if (p[m[j].to]==0)
{
ans--; //减去一个不能到达的点
p[m[j].to]++; //标记走过
f[++t]=m[j].to; //进入队列
}
}
}while (h<t&&ans>0); //广搜找能到达的点
if (ans==0) //能到达所有点
{
cout<<i<<endl;
return 0;
}
}
cout<<-1<<endl;
fclose(stdin);
fclose(stdout);
return 0;
}