質問:
凸型の船体を形成する家がいくつかあります。
家の間には鉄道があります。あなたは家からこれらの鉄道を横断することができますが、道は交差したり、ポイントを通り過ぎたりしてはいけません。
移動する最大距離を見つけます。
アイデア:
リングのインターバル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;
}