采花生(PAT)

1.题目描述

鲁宾逊先生有一只宠物猴,名叫多多。这天,他们两个正沿着乡间小路散步,突然发现路边的告示牌上贴着一张小小的纸条:“欢迎免费品尝我种的花生!——熊字”。
鲁宾逊先生和多多都很开心,因为花生正是他们的最爱。在告示牌背后,路边真的有一块花生田,花生植株整齐地排列成矩形网格。有经验的多多一眼就能看出,每棵花生植株下的花生有多少。为了训练多多的算术,鲁宾逊先生说:“你先找出花生最多的植株,去采摘它的花生;然后再找出剩下的植株里花生最多的,去采摘它的花生;依此类推,不过你一定要在我限定的时间内回到路边。”
我们假定多多在每个单位时间内,可以做下列四件事情中的一件:
1. 从路边跳到最靠近路边(即第一行)的某棵花生植株;
2. 从一棵植株跳到前后左右与之相邻的另一棵植株;
3. 采摘一棵植株下的花生;
4. 从最靠近路边(即第一行)的某棵花生植株跳回路边。

现在给定一块花生田的大小和花生的分布,请问在限定时间内,多多最多可以采到多少个花生?(注意可能只有部分植株下面长有花生)
假设这些植株下的花生个数各不相同。例如花生田里只有位于(2, 5), (3, 7), (4, 2), (5, 4)的植株下长有花生,个数分别为 13, 7, 15, 9。多多在 21 个单位时间内,只能经过(4, 2)、(2, 5)、(5, 4),最多可以采到 37 个花生。

2.输入描述:

输入包含多组数据,每组数据第一行包括三个整数 M(1≤M≤20)、N(1≤N≤20)和 K(0≤K≤1000),用空格隔开;表示花生田的大小为 M * N,多多采花生的限定时间为 K个单位时间。
紧接着 M 行,每行包括 N 个自然数 P(0≤P≤500),用空格隔开;表示花生田里植株下花生的数目,并且除了0(没有花生),其他所有植株下花生的数目都不相同。

3.输出描述:

对应每一组数据,输出一个整数,即在限定时间内,多多最多可以采到花生的个数。

4.输入例子:

6 7 21
0 0 0 0 0 0 0
0 0 0 0 13 0 0
0 0 0 0 0 0 7
0 15 0 0 0 0 0
0 0 0 9 0 0 0
0 0 0 0 0 0 0

5.输出例子:

37

6.解题思路:

1、首先要看清题目,以第一行为出发点;
2、虽然题目给出的是二维的数组结构,但我们可以转化为一维结构来简化问题
3、那就是用结构体分别存储植株的三个属性,植株的横、纵坐标x,y以及花生数量
4、然后还是审题,题目要求我们的是依次找出最多花生的植株,而不是怎样才能采到最多的花生(显然后者似乎更难)
5、于是我们只用对植株结构体的一维数组中的植株数量进行从大到小排序
6、最后一步就是如何从一棵移动到另一棵植株,这时候我们就可以在二维矩阵中以两棵植株为对角线画出一个矩形,坐标相减并取绝对值相加,也就是两棵植株的移动单位;
7、最后一点注意的就是题目中的3,4条件所描述的移动单位。

7.源代码:

#include<stdio.h>
typedef struct
{
	int x,y;//植株的位置
	int num;//花生的数量
}Peanut;
void sort(Peanut p[],int k)//冒泡排序
{
	Peanut temp;
	int i,j,flag;
	for(i=0;i<k;i++)
	{
		flag=0;
		for(j=0;j<k-i-1;j++)
			if(p[j].num<p[j+1].num)
			{
				temp=p[j];
				p[j]=p[j+1];
				p[j+1]=temp;
				flag=1;
			}
		if(flag==0)
			break;
	}
}
int main()
{
	Peanut p[500];	
	int M,N,K;
	while( scanf("%d %d %d",&M,&N,&K)!=-1)
	{
		int i,j,k=0,x,y,num=0,sum=0;
		for(i=0;i<M;i++)
			for(j=0;j<N;j++)
			{
				scanf("%d",&num);
				if(num)//有花生的植株
				{
					p[k].x=i;
					p[k].y=j;
					p[k++].num=num;
				}
			}
		sort(p,k);//从大到小排序有花生的植株

		i=0;	
		x=-1;//起始横坐标,(条件4)
		y=p[i].y;//起始纵坐标
		while(i<k)
		{
			x-=p[i].x;	y-=p[i].y;//取两点之间的横纵坐标之差
			x<0?x=-x:0;	y<0?y=-y:0;//取两点之间横纵坐标之差的绝对值
			K=K-x-y-1;//总移动单位减去两点之间的移动单位
			if(K-p[i].x-1<0)//判断采完本次花生后是否能回到路边
				break;
			//如果采摘完花生后能够回到路边,则本次采摘花生是有效的
			//否则不能回到路边就是无效的,花生数量也不必增加
			x=p[i].x;	y=p[i].y;//记录移动后当前坐标位置
			sum+=p[i++].num;//计数采摘的花生数
		}	
		printf("%d\n",sum);
	}	
	return 0;
}
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务