设d(i, j)为连通第i个点到第j个点的树的最小长度,则有状态转移方程:
d(i, j) = min{ d(i, k) + d(k + 1, j) + p[k].y – p[j].y + p[k+1].x – p[i].x }
然后用四边形不等式优化之。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#define MP make_pair
#define x first
#define y second
using namespace std; typedef pair<int, int> PII; const int maxn = + ;
const int INF = 0x3f3f3f3f;
int n; PII p[maxn]; int d[maxn][maxn], s[maxn][maxn]; int main()
{
while(scanf("%d", &n) == && n)
{
for(int i = ; i <= n; i++) scanf("%d%d", &p[i].x, &p[i].y);
for(int i = ; i <= n; i++)
{
s[i][i + ] = i;
d[i][i + ] = p[i+].x - p[i].x + p[i].y - p[i+].y;
} for(int l = ; l <= n; l++)
{
for(int i = ; i + l - <= n; i++)
{
int j = i + l - ;
d[i][j] = INF;
for(int k = s[i][j-]; k <= s[i+][j]; k++)
{
int t = d[i][k] + d[k+][j] + p[k].y - p[j].y + p[k+].x - p[i].x;
if(t < d[i][j])
{
d[i][j] = t;
s[i][j] = k;
}
}
}
} printf("%d\n", d[][n]);
} return ;
}
代码君