NYOJ195 飞翔

飞翔

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

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

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

 

没有障碍,也没有死路。这样设计主要是为了高速飞行的鹰们不要发现死路来不及调整而发生意外。潘帕斯雄鹰冒着减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 2
3
1 1
3 2
1 2
样例输出
383

/*
代码一:
    想着用递归来做,依次求出到某个点的最短距离,后来发现数据量太大,不允许
测试结果也不正确。。。。。。
#include <cstdio>
#include <cmath>
#include <iostream>

using namespace std;

const int N = 1001;
bool map[N][N];

double min1(double x, double y, double z)
{
    if(x - y > 1e-6)
    {
        if(x - z > 1e-6)
            return x;
        return z;
    }
    else if(y - z > 1e-6)
        return y;
    return z;
}

double min2(double x, double y)
{
    if(x - y > 1e-6)
        return x;
    return y;
}
double dis(int n, int m)
{
    if(n == 1 && m ==1)
        return 0;
    if(n == 1)
        return 1 + dis(1, m - 1);
    if(m == 1)
        return 1 + dis(n - 1, 1);
    if(map[n - 1][m - 1])
        return min1(dis(n-1, m) + 1, dis(n, m-1) + 1, sqrt(2.0) + dis(n-1, m-1));
    else
        return min2(1 + dis(n-1, m), 1 + dis(n, m-1));
}

int main()
{
    int n, m, k, i, j;
    while(~scanf("%d%d", &n, &m))
    {
        memset(map, false, sizeof(map));
        scanf("%d", &k);
        while(k--)
        {
            scanf("%d%d", &i, &j);
            map[i][j] = true;
        }
        printf("%d\n", dis(n, m));
    }
    return 0;
}

代码二:-------AC
    对所有特殊节点进行排序,求出最长满足条件的序列即可*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

struct node
{
    int x;
    int y;
}a[1001];

bool cmp(node p1, node p2)
{
    if(p1.x == p2.x)
        return p1.y < p2.y;
    return p1.x < p2.x;
}

int solve(int n)
{
    int cnt[1001];
    int max = 0;
    for(int i = 0; i < n; ++i)
    {
        cnt[i] = 1;
        for(int j = 0; j < i; ++j)
        {
            if(a[i].y > a[j].y && a[i].x > a[j].x && cnt[i] < cnt[j] + 1)
                cnt[i] = cnt[j] + 1;
        }
        if(max < cnt[i])
            max = cnt[i];
    }
    return max;
}

int main()
{
    int m, n, k, p;
    while(~scanf("%d%d", &n, &m))
    {
        scanf("%d", &k);
        for(int i = 0; i < k; ++i)
        {
            scanf("%d%d", &a[i].x, &a[i].y);
        }
        sort(a, a + k, cmp);
        //注意这里输出的格式要求是四舍五入,则只用控制小数点后的长度为0 即可
        printf("%.0lf\n", (n + m - ((2 - sqrt(2)) * solve(k)))* 100);
    }
    return 0;
}

  

功不成,身已退
原文地址:https://www.cnblogs.com/dongsheng/p/2914072.html