【NOI Online】 2021普及

【NOI Online】 2021普及

CCF NOI Online 能力测试
入门组
时间:2020 年 3 月 27 日 14:30 ∼ 2021 年 3 月 27 日 18:00
题目名称 切蛋糕 吃豆人 重力球
题目类型 传统型 传统型 传统型
目录 cake pacman ball
可执行文件名 cake pacman ball
输入文件名 cake.in pacman.in ball.in
输出文件名 cake.out pacman.out ball.out
每个测试点时限 1.0 秒 1.0 秒 1.0 秒
内存限制 256 MB 512 MB 512 MB
子任务数目 10 20 20
测试点是否等分 是 是 是
提交源程序文件名
对于 C++ 语言 cake.cpp pacman.cpp ball.cpp
编译选项
对于 C++ 语言 -lm
注意事项

  1. 文件名(包括程序名和输入输出文件名)必须使用英文小写。
  2. 结果比较方式为忽略行末空格、文末回车后的全文比较。
  3. C/C++ 中函数 main() 的返回值类型必须是 int,值为 0。
  4. 输入数据中,若一行内包含多个整数,则相邻两个整数均以一个空格分隔。不保
    证输入数据的行末没有多余空格。
    CCF NOI Online 能力测试 入门组 切蛋糕(cake)

切蛋糕(cake)

【题目描述】
Alice、Bob 和 Cindy 三个好朋友得到了一个圆形蛋糕,他们打算分享这个蛋糕。
三个人的需求量分别为 a, b, c,现在请你帮他们切蛋糕,规则如下:

  1. 每次切蛋糕可以选择蛋糕的任意一条直径,并沿这条直径切一刀(注意切完后不
    会立刻将蛋糕分成两部分)。
  2. 设你一共切了 n 刀,那么你将得到 2n 个扇形的蛋糕(特别地,切了 0 刀被认为
    是有一个扇形,即整个圆形蛋糕),将这些蛋糕分配给 Alice,Bob 和 Cindy,要
    求每个扇形蛋糕只能完整地分给一个人。
  3. 三人分到的蛋糕面积比需要为 a : b : c(不保证是最简比例,且如果 a, b, c 中某个
    数为 0,表示那个人不吃蛋糕)。
    为了完成这个任务,你至少需要切几刀?
    【输入格式】
    从文件 cake.in 中读入数据。
    本题单个测试点包含多组数据。
    第一行包含一个整数 T,表示数据组数。
    接下来 T 行,每行包含三个整数 a, b, c,表示三人的需求量。
    【输出格式】
    输出到文件 cake.out 中。
    输出 T 行,第 i 行的输出表示第 i 组数据中你至少需要切蛋糕的次数。
    【样例 1 输入】
    1 6 2 0 0 8
    3 0 5 3
    4 9 9 0
    5 6 2 4
    6 1 7 4
    7 5 8 5
    【样例 1 输出】
    1 0 2 2 3 1 4 2 5 3 6 2
    【样例 1 解释】
    【数据范围与提示】
    30% 的数据满足:a = b = 0。
    60% 的数据满足:a = 0。
    100% 的数据满足:1 ≤ T ≤ 104,0 ≤ a, b, c ≤ 108,保证 a + b + c > 0。 第 3 页 共 7 页
    CCF NOI Online 能力测试 入门组 吃豆人(pacman)

吃豆人(pacman)

【题目描述】
有一个 n 行 n 列的正方形点阵,左上角点坐标为 (1, 1),右下角点坐标为 (n, n)。
点阵中每个整点上都有数量不一的豆子,坐标为 (i, j) 的点上有 ai,j 个豆子。
你可以放置吃豆人,可以将点阵中任意的整点作为吃豆人的初始位置,再给定左上、
左下、右上、右下之一作为吃豆人的初始方向。
吃豆人会不断沿初始方向行进,吃光遇到的所有豆子,直到碰到点阵的边界,此时:

  1. 如果吃豆人处于正方形点阵四个角之一的位置,那么就会停止行动;
  2. 否则,吃豆人的行进路线将以这条边界为镜面发生反射,下图展示了一个路径某
    两次发生反射的例子:
    现在,你需要放置两个吃豆人,求两个吃豆人最多共能吃到多少个豆子?注意同一
    个豆子只能被吃一次。
    【输入格式】
    从文件 pacman.in 中读入数据。
    第一行包含一个整数 n,表示点阵大小。
    接下来 n 行,每行包含 n 个整数,其中第 i 行第 j 个整数表示 ai,j。
    【输出格式】
    输出到文件 pacman.out 中。
    输出一行一个整数,表示两个吃豆人最多共能吃到的豆子数量。
    【样例 1 输入】
    1 4 2 20 1 19 2
    3 3 18 4 17
    第 4 页 共 7 页
    CCF NOI Online 能力测试 入门组 吃豆人(pacman) 4 16 5 15 6
    5 7 14 8 13
    【样例 1 输出】
    1 132
    【样例 1 解释】
    在 (1, 1) 和 (1, 3) 位置放置吃豆人,初始方向分别为右下和左下,即可吃到位于
    (1, 1),(1, 3),(2, 2),(2, 4),(3, 1),(3, 3),(4, 2),(4, 4) 位置上的豆子,总个数为 132,
    达到最大,路径分别如下图绿线和红线所示:
    【数据范围与提示】
    对于 30% 的数据,n ≤ 3。
    对于 60% 的数据:n ≤ 100。
    对于 100% 的数据:2 ≤ n ≤ 1000,0 ≤ ai,j ≤ 103。 第 5 页 共 7 页
    CCF NOI Online 能力测试 入门组 重力球(ball)

重力球(ball)

【题目描述】
“重力球”游戏在一块 n × n 的正方形区域中进行,记从上往下第 i 行,从左往右
第 j 列的位置为 (i, j)。
正方形区域中存在 m 个障碍,第 i 个障碍占据位置 (xi
, yi),此外,正方形区域的
边界外都是障碍。
现在有两个小球,位置分别是 (a, b) 和 (c, d),在游戏中你可以进行如下操作:
• 指定上、下、左、右中的一个方向,将重力方向“切换”为这个方向。此时两个
小球会同时向这个方向移动,直到碰到障碍。
你要用最少的操作次数使得两个小球到达同一个位置。
现有 q 局游戏,每局游戏中只有小球的初始位置不同,而障碍位置是不变的,你需
要对每局游戏都求出最小操作次数,或报告无解。
【输入格式】
从文件 ball.in 中读入数据。
第一行包含三个整数 n, m, q,分别表示矩形区域大小,障碍个数和游戏局数。
接下来 m 行,每行包含两个整数 xi
, yi,表示位置 (xi
, yi) 上有一个障碍。数据保证
所有障碍所处的位置互不相同。
接下来 q 行,每行四个整数 a, b, c, d,表示一局游戏中两个小球的初始位置,保证
初始位置不存在障碍。
【输出格式】
输出到文件 ball.out 中。
输出共 q 行,第 i 行输出一个整数表示第 i 局游戏需要的最小操作次数,如果无解
则输出 -1。
【样例 1 输入】
1 4 4 3
2 2 2
3 2 4
4 3 2
5 4 4
6 1 3 4 3
7 2 1 2 1
第 6 页 共 7 页
CCF NOI Online 能力测试 入门组 重力球(ball) 8 1 2 3 4
【样例 1 输出】
1 1 2 0 3 3
【样例 1 解释】
该样例中障碍分布如图中红叉所示。
第一组询问中只需将重力改向上(或改向下)即可使两球同时到达。
第二组询问中两球已经在同一位置故不需操作。
第三组询问中改变 3 次重力的方向,依次改为向右、向下、向左,小球移动路线分
别如图中粉色、橙色、棕色线所示:
【数据范围与提示】
对于 20% 的数据:n, m ≤ 2。
对于 50% 的数据:n, m ≤ 30。
对于另外 30% 的数据:q = 1。
对于 100% 的数据:1 ≤ n, m ≤ 250,1 ≤ q ≤ 105,1 ≤ xi, yi, a, b, c, d ≤ n。

代码

T1

100

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std; 
int main()
{
	freopen("cake.in","r",stdin);
	freopen("cake.out","w",stdout);
	long long T,i,s,a[3];
	for(scanf("%lld",&T);T--;)
	{
		for(s=0,i=0;i<3;i++)
		{
			scanf("%lld",&a[i]);
			s+=(a[i]==0);
		}
		sort(a,a+3);
		if(s==2)printf("0\n");
		else
		{
			if(s==1)
			{
				if(a[1]==a[2])printf("1\n");
				else printf("2\n");
			}
			else
			{
				if(a[0]==a[1]||a[1]==a[2]||(a[0]+a[1]==a[2]))printf("2\n");
				else printf("3\n");
			}
		}
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}

T2

100

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int a[2010][2010],sum[2010];
int main()
{
	freopen("pacman.in","r",stdin);
	freopen("pacman.out","w",stdout);
	int n,i,j,x,y,ans=0,mx;
	memset(a,0,sizeof(a));
	memset(sum,0,sizeof(sum));
	scanf("%d",&n);
	for(i=1;i<=n;i++)
		for(j=1;j<=n;j++)
			scanf("%d",&a[i][j]);
	for(x=1,y=1;x<=n&&y<=n;x++,y++)sum[1]+=a[x][y];
	for(x=n,y=1;x>0&&y<=n;x--,y++)sum[n]+=a[x][y];
	for(i=2;i<n;i++)
	{
		sum[i]=-a[i][1];
		for(x=i,y=1;x>0&&y<=n;x--,y++)sum[i]+=a[x][y];
		for(x++,y--,x++,y++;x<=n&&y<=n;x++,y++)sum[i]+=a[x][y];
		for(x--,y--,x++,y--;x<=n&&y>0;x++,y--)sum[i]+=a[x][y];
		for(x--,y++,x--,y--;x>0&&y>0;x--,y--)sum[i]+=a[x][y];
	}
//	for(i=1;i<=n;i++)cout<<sum[i]<<endl;
//	mx=max(sum[1],sum[n])
	ans=sum[1]+sum[n]-(n&1)*a[(n+1)>>1][(n+1)>>1];
	for(i=2;i<n;i++)
	{
		ans=max(ans,sum[i]);
		if(i&1)
			ans=max(ans,sum[1]+sum[i]-a[(i+1)>>1][(i+1)>>1]-a[n+1-((i+1)>>1)][n+1-((i+1)>>1)]);
		else
			ans=max(ans,sum[1]+sum[i]);
		if((n-i)&1) 
			ans=max(ans,sum[n]+sum[i]);
		else
			ans=max(ans,sum[n]+sum[i]-a[i+1][n-i]-a[n-i][i+1]);
	}
	for(i=2;i<n;i++)
	{
		for(j=i+1;j<n;j++)
		{
			if((j-i)&1)
				ans=max(ans,sum[i]+sum[j]);
			else
				ans=max(ans,sum[i]+sum[j]-a[((i+j)>>1)][((j-i)>>1)+1]-a[((j-i)>>1)+1][((i+j)>>1)]-a[n+1-((i+j)>>1)][n-((j-i)>>1)]-a[n-((j-i)>>1)][n+1-((i+j)>>1)]);
		}
	}
	printf("%d",ans);
	fclose(stdin);
	fclose(stdout);
	return 0;
}

T3

25

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct jgt
{
	int a,b,c,d,s,f;
};
queue<jgt>que;
bool map[260][260];
int change[260][260][4][2];
bool vis[101][101][101][101];
int n,way[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
void BFS(int a,int b,int c,int d)
{
	int i;
	jgt tem,temp;
	vis[a][b][c][d]=1;
	if(a==c&&b==d)
	{
		printf("0\n");
		return;
	}
	for(i=0;i<4;i++)
	{
		tem.a=change[a][b][i][0];
		tem.b=change[a][b][i][1];
		tem.c=change[c][d][i][0];
		tem.d=change[c][d][i][1];
		tem.f=i;
		tem.s=1;
		if(tem.a==tem.c&&tem.b==tem.d)
		{
			printf("1\n");
			return;
		}
		if(!vis[tem.a][tem.b][tem.c][tem.d])
		{
			vis[tem.a][tem.b][tem.c][tem.d]=1;
			que.push(tem);
		}
	}
	for(;!que.empty();que.pop())
	{
		tem=que.front();
		temp.a=change[tem.a][tem.b][(tem.f+1)%4][0];
		temp.b=change[tem.a][tem.b][(tem.f+1)%4][1];
		temp.c=change[tem.c][tem.d][(tem.f+1)%4][0];
		temp.d=change[tem.c][tem.d][(tem.f+1)%4][1];
		temp.f=(tem.f+1)%4;
		temp.s=tem.s+1;
		if (temp.a==temp.c&&temp.b==temp.d)
		{
			printf("%d\n",temp.s);
			return;
		}
		if(!vis[temp.a][temp.b][temp.c][temp.d])
		{
			vis[temp.a][temp.b][temp.c][temp.d]=1;
			que.push(temp);
		}
		temp.a=change[tem.a][tem.b][(tem.f+3)%4][0];
		temp.b=change[tem.a][tem.b][(tem.f+3)%4][1];
		temp.c=change[tem.c][tem.d][(tem.f+3)%4][0];
		temp.d=change[tem.c][tem.d][(tem.f+3)%4][1];
		temp.f=(tem.f+3)%4;
		temp.s=tem.s+1;
		if (temp.a==temp.c&&temp.b==temp.d)
		{
			printf("%d\n",temp.s);
			return;
		}
		if(!vis[temp.a][temp.b][temp.c][temp.d])
		{
			vis[temp.a][temp.b][temp.c][temp.d]=1;
			que.push(temp);
		}
	}
	printf("-1\n");
	return;
}
int main()
{
	int m,q,i,j,k,x,y,x1,y1;
	freopen("ball.in","r",stdin);
	freopen("ball.out","w",stdout);
	scanf("%d%d%d",&n,&m,&q);
	memset(map,0,sizeof(map));
	for(i=1;i<=m;i++)
		scanf("%d%d",&x,&y),map[x][y]=1;
	for(i=1;i<=n;i++)
		for(j=1;j<=n;j++)
			for(k=0;k<4;k++)
			{
				for(x=i,y=j;1<=x&&x<=n&&1<=y&&y<=n&&!map[x][y];x+=way[k][0],y+=way[k][1]);
				change[i][j][k][0]=x-way[k][0],change[i][j][k][1]=y-way[k][1];
			}
	for(i=1;i<=q;i++)
	{
		memset(vis,0,sizeof(vis));
		scanf("%d%d%d%d",&x,&y,&x1,&y1);
		BFS(x,y,x1,y1);
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值