H - Lighthouses Gym - 102576H(区间DP,环形DP)

在这里插入图片描述

题意:
有一些房子,构成了一个凸包。
房子之间有铁路。你可以从一个房子出发遍历这些铁路,但是要求路径不能交叉,不能走走过的点。
求最多走多少距离。

思路:
环上的区间DP。
将房子看做圆,走了 i − > j i->j i>j后,就相当于把圆分为了两半,之后只能走其中一半。

定义 f [ i ] [ j ] [ 0 / 1 ] f[i][j][0/1] f[i][j][0/1]为还可以逆时针走 ( i , j ) (i,j) (i,j)部分的点,且下一次出发的点为 i ( j ) i(j) i(j)的最大所走距离。

因为我们规定了是逆时针方向的走,相当于是将区间扩大了一倍,这就不用担心环形结构的影响了。

之后就按照区间DP进行转移。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>
#include <iostream>
#include <cmath>
using namespace std;
typedef long long ll;

const int maxn = 305;

struct Node {
    
    
    double x,y;
}a[maxn];

double f[maxn][maxn][2],dis[maxn][maxn];

double get(Node a,Node b) {
    
    
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

int main() {
    
    
    int T;scanf("%d",&T);
    while(T--) {
    
    
        int n;scanf("%d",&n);
        for(int i = 0;i < n;i++) {
    
    
            scanf("%lf%lf",&a[i].x,&a[i].y);
        }
        memset(f,0,sizeof(f));
        memset(dis,0,sizeof(dis));
        int m;scanf("%d",&m);
        for(int i = 0;i < m;i++) {
    
    
            int x,y;scanf("%d%d",&x,&y);
            x--;y--;
            f[y][x][0] = f[y][x][1] = f[x][y][0] = f[x][y][1] = dis[x][y] = dis[y][x] = get(a[x],a[y]);
        }
        
        for(int len = n - 1;len >= 1;len--) {
    
    
            for(int i = 0;i < n;i++) {
    
    
                int j = (i + len) % n;
                for(int k = (i + 1) % n;k != j;k = (k + 1) % n) {
    
    
                    if(dis[k][j] > 0) {
    
    
                        f[i][k][1] = max(f[i][k][1],f[i][j][1] + dis[k][j]);
                        f[k][j][0] = max(f[k][j][0],f[i][j][1] + dis[k][j]);
                    }
                    if(dis[i][k] > 0) {
    
    
                        f[i][k][1] = max(f[i][k][1],f[i][j][0] + dis[i][k]);
                        f[k][j][0] = max(f[k][j][0],f[i][j][0] + dis[i][k]);
                    }
                }
            }
        }
        
        double ans = 0;
        for(int i = 0;i < n;i++) {
    
    
            for(int j = 0;j < n;j++) {
    
    
                ans = max(ans,max(f[i][j][0],f[i][j][1]));
            }
        }
        
        printf("%.10f\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/tomjobs/article/details/109025848