【纪中2020.4.01日】模拟赛题解

目录:

T1:Bucket Brigade
T2:Milk Factory
T3:Cow Evolution

USACO的题……原汁原味连标题都是英文,排面!

正题:

T1:Bucket Brigade

题目描述

农场上起火了,奶牛们正在紧急赶去灭火!
农场可以用一个像这样的10×10的字符方阵来描述:
在这里插入图片描述

字符’B’表示正着火的牛棚。字符’L’表示一个湖,而字符’R’表示农场上的一块巨大岩石。奶牛们想要沿着一条湖到牛棚之间的路径组成一条“水桶传递队列”,这样她们就可以沿着这条路径传递水桶来帮助灭火。当两头奶牛在东南西北四个方向上相邻时水桶可以在她们之间传递。这对于湖边的奶牛也是对的——奶牛只能在紧挨着湖的时候才能用水桶从湖里取水。类似地,奶牛只能在紧挨着牛棚的时候才能用水去灭牛棚的火。
请帮助求出奶牛们为了组成这样的“水桶传递队列”需要占据的’.'格子的最小数量。奶牛不能站在岩石所在的方格之内,此外保证牛棚和湖不是相邻的。

输入

输入包含10行,每行10个字符,描述这个农场的布局。输入保证图案中恰有一个字符’B’、一个字符’L’以及一个字符’R’。

输出

输出一个整数,为组成一条可行的水桶传递队列所需要的奶牛的最小数量。

样例输入

..........
..........
..........
..B.......
..........
.....R....
..........
..........
.....L....
..........

样例输出

7

分析:

一个广搜即最少步数。
先判断’B’的位置,标记,广搜判断中判断’R
最后,如果搜到了’L’,就输出当前广搜所用步数

CODE:

#include<iostream>
#include<cstdio>
using namespace std;
int n,m,f[100010][4];
char a[101][101];
bool bz[101][101];
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
int main(){
	freopen("buckets.in","r",stdin);
	freopen("buckets.out","w",stdout);
	n=m=10;
	for(int i=1;i<=10;i++){
		for(int j=1;j<=10;j++){
			cin>>a[i][j];
			if(a[i][j]=='B'){  //找出所有的'B',标记
				f[1][1]=i;
				f[1][2]=j;
				vis[i][j]=1;
			}
		}
	}
	int tail=1,head=0;
	while(head<tail){  //广搜
		head++;
		for(int i=0;i<4;i++){
			int xx=f[head][1]+dx[i];
			int yy=f[head][2]+dy[i];
			if(a[xx][yy]!='R'  /*非'R'再判断越界*/&&xx>=1&&xx<=n&&yy>=1&&yy<=m&&vis[xx][yy]==0){
				tail++;
				f[tail][1]=xx;
				f[tail][2]=yy;
				f[tail][3]=f[head][3]+1;
				vis[xx][yy]=1;
				if(a[xx][yy]=='L'){  //找到了'L'就输出步数
					cout<<f[head][3];
					return 0;
				}
			}
		}
	}
	return 0;
}

T2:Milk Factory

题目描述

牛奶生意正红红火火!Farmer John的牛奶加工厂内有N个加工站,编号为1…N(1≤N≤100),以及N−1条通道,每条连接某两个加工站。(通道建设很昂贵,所以Farmer John选择使用了最小数量的通道,使得从每个加工站出发都可以到达所有其他加工站)。
为了创新和提升效率,Farmer John在每条通道上安装了传送带。不幸的是,当他意识到传送带是单向的已经太晚了,现在每条通道只能沿着一个方向通行了!所以现在的情况不再是从每个加工站出发都能够到达其他加工站了。
然而,Farmer John认为事情可能还不算完全失败,只要至少还存在一个加工站i满足从其他每个加工站出发都可以到达加工站i。注意从其他任意一个加工站j前往加工站i可能会经过i和j之间的一些中间站点。请帮助Farmer John求出是否存在这样的加工站i。

输入

输入的第一行包含一个整数N,为加工站的数量。以下N−1行每行包含两个空格分隔的整数ai和bi,满足1≤ai,bi≤N以及ai≠bi。这表示有一条从加工站ai向加工站bi移动的传送带,仅允许沿从ai到bi的方向移动。

输出

如果存在加工站i满足可以从任意其他加工站出发都可以到达加工站i,输出最小的满足条件的i。否则,输出−1。

样例输入

3
1 2
3 2

样例输出

2

分析:

此题充满了玄学……
你当然可以依题意用图论
这道题说白了先排序,然后做判断
先判如果当前站编号等于它下一站编号,即不能全部走,输出’-1’(注意循环i=1;i<n-1;i++
然后判,如果当前站编号等于从小到大编号的顺序,直接输出当前编号。(这一切都是建立在排完序之后的有序状态之下)
还有说一下题库里数据:
1≤N≤100
但我数组开70为啥也能过?

CODE:

#include<cmath>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long LL;
int n,a[71],b[71];  //··11	
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",&a[i],&b[i]);
	sort(a+1,a+n);  //排序很重要
	for(int i=1;i<n-1;i++)
	{
		if(a[i]==a[i+1]){  //判条件①
			cout<<"-1"<<endl;
			return 0;
		} 
	}
	for(int i=1;i<n;i++)
	{
		if(a[i]!=i)  //再判条件②
		{
			cout<<i<<endl;
			return 0;
		} 
	}
	
return 0;
}

T3:Cow Evolution

题目描述

现在是3019年,在过去的一千年里发生了不计其数的牛类进化,产生了具有各种有趣特性的奶牛。
牛类进化的记录可以用一棵树来表示,起源是位于树根位置的没有特殊特性的奶牛。树上每一个产生后代的结点,有可能所有的奶牛都进化出了一种新的特性(比如说喷火(fire breathing),如下图所示,其中所有斑点(spots)奶牛最后都能喷火),或者是奶牛种群产生了分支进化,其中有些进化出了新的特性(比如,飞(flying)),有的没有。
在这里插入图片描述

树底部的叶结点表示3019年所有产生的奶牛的子种群。没有不同的叶结点(子种群)具有完全相同的一组特性。例如,子种群#1是没有特殊特性的奶牛,子种群#3是能够心灵感应的(telepathic)并且会飞的奶牛。相比之下,子种群#2是会飞但不能心灵感应的奶牛。子种群#3是唯一既会飞又会心灵感应的。
像上图这样每一种进化出的新特性都恰好在树中的一条边上产生(也就是说,在整个进化历史中仅在一个时间点产生),这样的进化树被称为是“合法的”。例如,如果斑点这一特性在两个不同分支中均进化产生,这棵进化树就不是合法的。给定3019年奶牛子种群的描述,请判断是否这可以由一棵合法的进化树所解释。

输入

输入的第一行包含子种群的数量N(2≤N≤25)。以下N行每行描述一个子种群。每行包含一个整数K(0≤K≤25),之后是K个该子种群奶牛所拥有的特性。特性是由至多20个小写字母(a…z)组成的字符串。没有两个子种群拥有完全相同的特性。

输出

如果可能构造一棵可以解释所有子种群产生途径的进化树,输出"yes",否则输出"no"。

样例输入

4
2 spots firebreathing
0
1 flying
2 telepathic flying

样例输出

yes

分析:

字符串处理
这道题乍一看好像很高级,实际只要枚举几种情况就好了。
:A是否包含B
:B是否包含A
:A与B是否相同
都不是则输出’no’,否则输出’yes

CODE:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
string s[31][31],a[31];
int m,u[31],n;
bool judge(string a,string b){
	bool f1=0,f2=0,f3=0,f4=0,f5=0;
	for(int i=1;i<=n;i++){
		f1=0,f2=0;
		for(int j=1;j<=u[i];j++){
			if(s[i][j]==a)f1=1;  //判断包含a
			if(s[i][j]==b)f2=1;  //判断包含b
		}
		if(f1&&!f2)f4=1;  //再判断a b两字符串互相包含
		if(f2&&!f1)f5=1;  //三种情况
		if(f1&&f2)f3=1;
	}
	return f4>0&&f5>0&&f3>0;  
}
int main(){
	freopen("evolution.in","r",stdin);
	freopen("evolution.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++){
		int k,sum=0;
		cin>>k;
		u[i]=k;
		for(int j=1;j<=k;j++){
			string str;
			cin>>str;
			sum++;
			s[i][sum]=str;
			bool flag=0;
			for(int i1=1;i1<=m;i1++){
				if(a[i1]==str){
					flag=1;
					break;
				}
			}
			if(!flag)m++,a[m]=str;  //填入新的
		}
	}
	int f=0;
	for(int i=1;i<=m;i++)
		for(int j=i+1;j<=m;j++)
			if(judge(a[i],a[j])) {
				cout<<"no";  //做完判断
				return 0;
			}
	cout<<"yes";
	return 0;
}

猜你喜欢

转载自blog.csdn.net/dgssl_xhy/article/details/105853227