nyoj195飞翔(动态规划)

时间:2022-07-01 11:09:02

飞翔

时间限制:3000 ms  |  内存限制:65535 KB 难度:4
描述

鹰最骄傲的就是翱翔,但是鹰们互相都很嫉妒别的鹰比自己飞的快,更嫉妒其他的鹰比自己飞行的有技巧。于是,他们决定举办一场比赛,比赛的地方将在一个迷宫之中。

这些鹰的起始点被设在一个N*M矩阵的左下角map[1,1]的左下角。终点被设定在矩阵的右上角map[N,M]的右上角,有些map[i,j]是可以从中间穿越的。每一个方格的边长都是100米。如图所示:

nyoj195飞翔(动态规划)

没有障碍,也没有死路。这样设计主要是为了高速飞行的鹰们不要发现死路来不及调整而发生意外。潘帕斯雄鹰冒着减RP的危险从比赛承办方戒备森严的基地中偷来了施工的地图。但是问题也随之而来,他必须在比赛开始之前把地图的每一条路都搞清楚,从中找到一条到达终点最近的路。(哈哈,笨鸟不先飞也要拿冠军)但是此鹰是前无古鹰,后无来鹰的吃菜长大的鹰--菜鸟。他自己没有办法得出最短的路径,于是紧急之下找到了学OI的你,希望找到你的帮助。

 

输入
本题有多组数据。以EOF为输入结束的标志。
每组测试数据的首行为n,m(0<n,m<=1000000),第2行为k(0<k<=1000)表示有多少个特殊的边。以下k行为两个数,i,j表示map[i,j]是可以直接穿越的。
输出
仅一行,1,1-->n,m的最短路径的长度,四舍五入保留到整数即可
样例输入
3 231 13 21 2
样例输出
383

思路:该题由于n,m的数据较大,无法根据模拟鹰的位置来进行动态规划,可以根据特殊的边这个线索来解决,先将这些特殊的边进行排序,然后选取最大的上升子序列个数,选取的特殊边越多,那飞翔的距离就会越短,有点类似于求区间最长上升子序列。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<string.h>
#define max(x,y)(x>y?x:y)
using namespace std;
double d=sqrt(100*100+100*100);
int dp[1010];
struct Point
{
int x;
int y;
}p[1010];
int comp(Point p1,Point p2)
{
if(p1.x==p2.x)
return p1.y<p2.y;
return p1.x<p2.x;
}
int main()
{
int i,j,n,m,k;
while(scanf("%d%d",&n,&m)!=EOF)
{

scanf("%d",&k);
for(i=1;i<=k;i++)
dp[i]=1;
for(i=1;i<=k;i++)
scanf("%d%d",&p[i].y,&p[i].x);
sort(p+1,p+k+1,comp);
for(i=1;i<=k;i++)
for(j=1;j<i;j++)
{
if(p[j].x<p[i].x&&p[j].y<p[i].y)
dp[i]=max(dp[i],dp[j]+1);
}
int res=0;
for(i=1;i<=k;i++)
{
res=max(res,dp[i]);
}
double s=res*d+(n+m-2*res)*100;
res=s*10;
if(res%10>=5){
res=res/10+1;
}else{
res/=10;
}
printf("%d\n",res);
}
return 0;
}