Ural 1119. Metro NYOJ 195 飞翔 解题报告

DP

1、每一行最多只可以走一次捷径,每一列也是最多只可以走一次捷径

2、每次走过捷径后的横坐标和纵坐标都要大于之前的坐标

只要求出从起点到终点所经过的最多的捷径,就能得到最少的路程。每一步的最优解用之前走过的路径所求,满足无后效性,每一个子状态都可以求出最优解,满足最优子结构,可以用dp解决。

f[i]=max(f[j]+1,f[i]);

j点坐标小于点,i点为捷径时,走到i点坐标时经过的最多捷径数=max(走到j点的最多捷径数+1,走到i点时的最多捷径数)

最后找出最大的f(i)就是能经过最多的捷径

注意坐标的输入没有顺序性,要进行排列。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
using  namespace std;
const  int MAXN=1003;
typedef  struct
{
     int a,b;
}point;
point p[MAXN];
int f[1003];
bool cmp(point p1,point p2)
{
     if(p1.a==p2.a)  return p1.b<p2.b;
     return p1.a<p2.a;
}
int main()
{
     // freopen("1.in","r",stdin);
     int m,n;
     while(cin>>n>>m)
    {
         int k;
        cin>>k;
         for( int i=0;i<k;i++)
        {
            cin>>p[i].a>>p[i].b;
            f[i]=1;
        }
        sort(p,p+k,cmp); // 如果横坐标相等,按照纵坐标从小到大排序,否则按照横坐标从小到大排序
         int v=0,flag=0;
        
         // dp
         for( int i=0;i<k;i++)
        {
             for( int j=0;j<=i;j++)
            {
                 if(p[i].a>p[j].a)
                {
                     if(p[i].b>p[j].b) f[i]=max(f[j]+1,f[i]);
                }
            }

        }
         // 求用到最多捷径的点
         int ma=*max_element(f,f+k);
        cout<<( int)((m+n-2*ma)*100+ma*100*sqrt(2.0)+0.5)<<endl;

    }


     return 0;
}
        

你可能感兴趣的:(Ural 1119. Metro NYOJ 195 飞翔 解题报告)