枚舉算法--討厭的青蛙

問題描述:

在一塊被踩踏的田地裏找尋被踩踏路徑最長的一條道路,並輸出被踩踏的稻田數目。其中:要求路線爲直線(包括斜直線),至少有三顆稻子被踩到,每兩顆被踩到的稻子之間的距離是相等的;輸入爲:第一行爲總的行數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;
}


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