【纪中2020.4.15日】模拟赛题解

目录:

T1:Grass Planting
T2:Icy Perimeter
T3:Mountain View

这次的还是USACO的题……真的每次模拟赛做的都是奶牛题我人傻了……

正题:

T1:Grass Planting

题目描述

到了一年中Farmer John在他的草地里种草的时间了。整个农场由N块草地组成(1≤N≤10^5),方便起见编号为1…N,由N−1条双向的小路连接,每块草地都可以经过一些小路到达其他所有的草地。
Farmer John当然可以在每块草地里种不同种类的草,但是他想要使得使用的草的种类数最小,因为他用的草的种类数越多,他就需要负担更高的花费。
不幸的是,他的奶牛们对选择农场上的草表现得十分苛刻。如果两块相邻(由一条小路直接相连)的草地种了同一种草,或者即使是两块接近相邻(均可由一条小路直接连向同一块草地)的草地,那么奶牛们就会抱怨她们进餐的选择不够多样。Farmer John能做的只能是抱怨这些奶牛,因为他知道她们不能被满足的时候会制造多大的麻烦。
请帮助Farmer John求出他的整个农场所需要的最少的草的种类数。

输入

输入的第一行包含N。以下N−1行每行描述了一条小路连接的两块草地。

输出

输出Farmer John需要使用的最少的草的种类数。

样例输入

4
1 2
4 3
2 3

样例输出

3

分析:

此题十分简单,以至于我都打了万能头……
标记,找最大值,输出,结束
要输出ans+1

CODE:

#include<bits/stdc++.h>
using namespace std;
int n,a[100001];
int main(){
	freopen("planting.in","r",stdin);
	freopen("planting.out","w",stdout);
    cin>>n;
    int x,y;
    for(int i=1;i<n;i++)
    {
    	cin>>x>>y;
    	a[x]++;a[y]++;  //标记
	}
    int ans=0;
    for(int i=1;i<=n;i++){
        if(a[i]>ans){  //找最大值
            ans=a[i];
        }
    }
    cout<<ans+1;  //输出ans+1
}

T2:Icy Perimeter

题目描述

Farmer John要开始他的冰激凌生意了!他制造了一台可以生产冰激凌球的机器,然而不幸的是形状不太规则,所以他现在希望优化一下这台机器,使其产出的冰激凌球的形状更加合理。
机器生产出的冰激凌的形状可以用一个N×N(1≤N≤1000)的矩形图案表示,例如:
在这里插入图片描述
每个’.‘字符表示空的区域,每个’#‘字符表示一块1×1的正方形格子大小的冰激凌。
不幸的是,机器当前工作得并不是很正常,可能会生产出多个互不相连的冰激凌球(上图中有两个)。一个冰激凌球是连通的,如果其中每个冰激凌的正方形格子都可以从这个冰激凌球中其他所有的冰激凌格子出发重复地前往东、南、西、北四个方向上相邻的冰激凌格子所到达。
Farmer John想要求出他的面积最大的冰激凌球的面积和周长。冰激凌球的面积就是这个冰激凌球中’#'的数量。如果有多个冰激凌球并列面积最大,他想要知道其中周长最小的冰激凌球的周长。在上图中,小的冰激凌球的面积为2,周长为6,大的冰激凌球的面积为13,周长为22。
注意一个冰激凌球可能在中间有“洞”(由冰激凌包围着的空的区域)。如果这样,洞的边界同样计入冰激凌球的周长。冰激凌球也可能出现在被其他冰激凌球包围的区域内,在这种情况下它们计为不同的冰激凌球。例如,以下这种情况包括一个面积为1的冰激凌球,被包围在一个面积为16的冰激凌球内:
在这里插入图片描述
同时求得冰激凌球的面积和周长十分重要,因为Farmer John最终想要最小化周长与面积的比值,他称这是他的冰激凌的“冰周率”。当这个比率较小的时候,冰激凌化得比较慢,因为此时冰激凌单位质量的表面积较小。

输入

输入的第一行包含N,以下N行描述了机器的生产结果。其中至少出现一个’#'字符。

输出

输出一行,包含两个空格分隔的整数,第一个数为最大的冰激凌球的面积,第二个数为它的周长。如果多个冰激凌球并列面积最大,输出其中周长最小的那一个的信息。

样例输入

6
##....
....#.
.#..#.
.#####
...###
....##

样例输出

13 22

分析:

这道题就是广搜,周长就是判断旁边遇到了"."就周长+1
先在主函数中把符号换成0与1,再每个点广搜

CODE:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
int a[1010][1010],st[1000010][3],v[1010][1010],head,tail,ans1,ans2,n,x,y;
const int dx[5]={0,1,0,0,-1};  //导航
const int dy[5]={0,0,1,-1,0};
char c;
bool check(int x,int y){
	if(x>0&&x<=n&&y>0&&y<=n&&a[x][y]==1&&v[x][y]==0)
	return 1;  //判断边界
	else
	return 0;
}
void bfs(int x,int y){  //广搜
	head=0,tail=1;
    int xx,yy,x1,y1;
	st[1][1]=x;
	st[1][2]=y;
    v[x][y]=1;
    int num1=1,num2=0;
    for(int i=1; i<=4; i++) {
        xx=x+dx[i];
        yy=y+dy[i];
        if(a[xx][yy]==0) //计数周长
            num2++;
    }
	do
	{
		head++;
		for(int i=1;i<=4;i++)
		{
            xx=st[head][1]+dx[i],yy=st[head][2]+dy[i];
			if(check(xx,yy))
			{
				tail++;
                num1++;  //计数面积
				st[tail][1]=xx;
				st[tail][2]=yy;
				v[xx][yy]=1;
                for(int j=1;j<=4;j++) {
                    x1=xx+dx[j];
                    y1=yy+dy[j];
                    if(a[x1][y1]==0)
                        num2++;  //继续计数
                }
			}
		} 
	}while(head<=tail);
    if(num1>ans1) {  //还要找最后的面积
        ans1=num1;
        ans2=num2;
    } else if(num1==ans1) {
        if(num2<ans2) {
            ans2=num2;  //周长
        }
    }
	return;
}
int main(){
	freopen("perimeter.in","r",stdin);
	freopen("perimeter.out","w",stdout);
	scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            cin>>c;
            if(c=='#') a[i][j]=1;  //替换
        }
    }
    for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(a[i][j]==1&&v[i][j]==0)  //每个点广搜
			   bfs(i,j);	
		}
	}
    printf("%d %d",ans1,ans2);
}

T3:Mountain View

题目描述

从农场里奶牛Bessie的牧草地向远端眺望,可以看到巍峨壮丽的山脉绵延在地平线上。山脉里由N座山峰(1≤N≤10^5)。如果我们把Bessie的视野想象成xy平面,那么每座山峰都是一个底边在x轴上的三角形。山峰的两腰均与底边成45度角,所以山峰的峰顶是一个直角。于是山峰i可以由它的峰顶坐标(xi,yi)精确描述。没有两座山峰有完全相同的峰顶坐标。
Bessie尝试数清所有的山峰,然而由于它们几乎是相同的颜色,所以如果一座山峰的峰顶在另一座山峰的三角形区域的边界上或是内部,她就无法看清。
请求出Bessie能够看见的不同的山峰的峰顶的数量,也就是山峰的数量。

输入

输入的第一行包含N。以下N行每行包含xi(0≤xi≤109)和yi(1≤yi≤109),描述一座山峰的峰顶的坐标。

输出

输出Bessie能够分辨出的山峰的数量。

样例输入

3
4 6
7 2
2 5

样例输出

2

分析:

排序,关键字x坐标,从小到大或相等但y大于
然后找最大值计数

CODE:

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
int n,x,y,maxn=-10000000,ans;
struct c{
    int l,r;
}a[100010];
bool cmp(const c&q,const c&p)
{
    return q.l<p.l||(q.l==p.l&&q.r>p.r);  //排序函数
}
int main(){
	freopen("mountains.in","r",stdin);
	freopen("mountains.out","w",stdout);
	scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&x,&y);
        a[i].l=x-y;
        a[i].r=x+y;
    }
    sort(a+1,a+n+1,cmp);  //排序
    for(int i=1;i<=n;i++)
    {
        if(a[i].r>maxn)  //找最大
        {
            ans++;  //计数
            maxn=a[i].r;  //赋值
        }
    }
    printf("%d",ans);
}

猜你喜欢

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