H-灯台ジム-102576H(インターバルDP、サーキュラーDP)

ここに写真の説明を挿入

質問:
凸型の船体を形成する家がいくつかあります。
家の間には鉄道があります。あなたは家からこれらの鉄道を横断することができますが、道は交差したり、ポイントを通り過ぎたりしてはいけません。
移動する最大距離を見つけます。

アイデア:
リングのインターバルDP。
家を円と考えて、i −> j i-> jに行きますi >>jの後は、円を2つに分割するのと同じで、半分しか歩くことができません。

定义 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 最大移動距離。

反時計回りに間隔を2倍にすることを規定しているので、リング構造の影響を気にする必要はありません。

その後、間隔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