枚举算法--讨厌的青蛙

问题描述:

在一块被踩踏的田地里找寻被踩踏路径最长的一条道路,并输出被踩踏的稻田数目。其中:要求路线为直线(包括斜直线),至少有三颗稻子被踩到,每两颗被踩到的稻子之间的距离是相等的;输入为:第一行为总的行数r和列数c,第二行为共有多少颗水稻被踩,第三行往下为水稻被踩的行数和列数。输出为:最长的被踩踏的稻子数目,若没有则输出0。

基本思路:

1,首先需要确定前两颗被踩踏的座标,由前两个座标便可以确定一条路径,设座标为(X1,Y1),(X2,Y2),则两者之间的为间隔dX=X2-X1,dY=Y2-Y1;

2,要求第一点的前一点要在稻田外,若不在,则第一点不满足第一点,第三点则要求在稻田内,最后一点的后面一点要落在稻田外,设座标(X0,Y0),(X3,Y3);X0=X1-dX,Y0=Y1-dY;Xi=X1+i*dX,Yi=Y1+i*dY;(i>=3)

3,猜测的过程中一定要尽快的排除错误!当满足如下条件的时候,就要排除最先选取的两点了:a,青蛙不能经过一跳从稻田外跳到第一点上去;b,按照第一点和第二点确定步长,从第一点出发,青蛙最多经过(MAXSTEPS-1)步,就会跳跃到稻田之外;c,MAXSTEPS是当前已经找到的最好的答案。

4,选取合适的数据结构:关于被踩踏的水稻座标最好采用单个变量的形式,简单清晰,此处采用结构体表示座标;

struct Plant{
int x,y;//x,y分别表示水稻的行号和列号
}

5,猜测一条行走路径,需要从当前位置(X,Y)出发时,判断(X+dX,Y+dY)位置的水稻是否被踩踏;先采用sort()函数对plants中的元素排序,再用binary_search()从中查找元素(X+dX,Y+dY)。

程序代码:

#include<iostream>
#include<stdlib.h>
#include<algorithm>
using namespace std;
//讨厌的青蛙
int r, c, n;//r为稻田的行数,c为稻田的列数,n为被踩踏的稻子数目

struct  PLANT
{
	int x;
	int y;
};
PLANT plants[5001];//所有稻子的座标
PLANT  plant;//单个稻子的座标

int BinarySearch(PLANT pla, int a, int b);
int main()
{
	int i, j, steps;
	int px, py, dx, dy;
	int max = 2;
	printf("输入稻田的行数和列数以及被踩踏的稻子的数目和座标:\n");
	scanf_s("%d%d", &r, &c);
	scanf_s("%d", &n);
	for (i = 0; i < n; ++i)
		scanf_s("%d%d", &plants[i].x, &plants[i].y);
	sort(plants, plants + n);//对输入的座标进行排序,x小先排,若x相同则y小先排
	for (i = 0; i < n; ++i)
		printf("%d%d\n", plants[i].x,plants[i].y);
	for (i = 0; i < n - 2; ++i)//i是第一个点,j是第二个点
		for (j = i + 1; j < n - 1; ++j)
		{
			dx = plants[j].x - plants[i].x;//计算x的行距
			dy = plants[j].y - plants[i].y;//计算y的行距
			px = plants[i].x - dx;//上一颗水稻的横座标
			py = plants[i].y - dy;//上一颗水稻的纵座标
			if (px <= r&&px >= 1 && py <= c&&py >= 1)
				continue;//若第一课水稻的座标在稻田里面,说明第一步的间距太小了,需要变长一些,取下一个点作为第二点
			if ((plants[i].x + (max-1)*dx)>r)//若第二步在田外,则选取的不合适,重新选取第一个点
				break;//x方向过早过界了,第一点不成立
			//lost
			int pY;
			pY = plants[i].y + (max - 1)*dy;
			if (pY > c || pY < 1)
				continue;//y方向过早过界了,第二点不成立
			steps = BinarySearch(plants[j], dx, dy);
			if (steps > max)
				max = steps;
		}
	if (max == 2)
		max = 0;
	printf("%d\n", max);
}

int BinarySearch(PLANT pla, int dx, int dy)
{
	int steps;
	plant.x = pla.x + dx;
	plant.y = pla.y + dy;
	steps = 2;
	while (plant.x <= r&&plant.x >= 1 && plant.y <= c&&plant.y >= 1)
	{
		if (!binary_search(plants, plants + n,plant))//二分查找函数,若是用到其他的数据则需要使用"operator<",是bool类型
		{
			steps = 0;
			break;
		}
		plant.x += dx;
		plant.y += dy;
		steps++;
	}
	return steps;
}

bool operator <(const PLANT &p1, const PLANT &p2)
{
	if (p1.x == p2.x)
		return p1.y < p2.y;
	return p1.x < p2.x;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章