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