vijos 1069 新年趣事之红包(区间DP)

题目:https://vijos.org/p/1069

题意:给你一个凸包,问遍历所有点一遍的最短路径

分析:由于图形是一个凸包,所以肯定是选一个点,然后从两端不断拓展出去,假设已经拓展[i , i+len ]这几个点,且f[ i ][ len ][0]为遍历这些点,且终点为i的最短路,f[ i ] [len] [1]为遍历这些点,且终点为i+len的最短路,那么有

             f[i][len][0]=min(f[(i+1)%n][len-1][0]+d[i][(i+1)%n],
                             f[(i+1)%n][len-1][1]+d[i][(i+len)%n]);
            f[i][len][1]=min(f[i][len-1][0]+d[(i+len)%n][i],
                             f[i][len-1][1]+d[(i+len)%n][(i+len-1)%n]);

也就是区间[i , i+len] 终点在i的情况,一定是从区间[i+1, i+len]转化过来的,就两种情况,从i+1到i, 或从+len 到i,另一种情况类似

然后注意下初始化就行了,说实话, 这题卡住了, 看了题解 = =

代码:

/** head files*/
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <list>
#include <stdexcept>
#include <functional>
#include <utility>
#include <ctime>
using namespace std;

/** some operate*/
#define PB push_back
#define MP make_pair
#define REP(i,n) for(i=0;i<(n);++i)
#define FOR(i,l,h) for(i=(l);i<=(h);++i)
#define FORD(i,h,l) for(i=(h);i>=(l);--i)
#define MSET(arr,val) memset(arr,val,sizeof(arr))
#define MAX3(a,b,c) max(a,max(b,c))
#define MAX4(a,b,c,d) max(max(a,b),max(c,d))
#define MIN3(a,b,c) min(a,min(b,c))
#define MIN4(a,b,c,d) min(min(a,b),min(c,d))

/** some const*/
#define N 888
#define M 222222
#define PI acos(-1.0)
#define oo 1111111111

/** some alias*/
typedef long long ll;

/** Global variables*/
double f[N][N][2],d[N][N];
double x[N],y[N];

/** some template names, just push ctrl+j to get it in*/
//manacher 求最长回文子串
//pqueue 优先队列
//combk n元素序列的第m小的组合和
//pmatrix n个点的最大子矩阵

int main()
{
    int i,j,len,n;
    scanf("%d",&n);
    REP(i,n)scanf("%lf%lf",&x[i],&y[i]);
    REP(i,n)REP(j,n)
        d[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
    REP(i,n)f[i][0][0]=f[i][0][1]=0;
    FOR(len,1,n-1)
        REP(i,n)
        {
            f[i][len][0]=min(f[(i+1)%n][len-1][0]+d[i][(i+1)%n],
                             f[(i+1)%n][len-1][1]+d[i][(i+len)%n]);
            f[i][len][1]=min(f[i][len-1][0]+d[(i+len)%n][i],
                             f[i][len-1][1]+d[(i+len)%n][(i+len-1)%n]);
        }
    double ans=1e30;
    REP(i,n)ans=MIN3(ans,f[i][n-1][0],f[i][n-1][1]);
    printf("%.3lf\n",ans);
	return 0;
}


你可能感兴趣的:(vijos 1069 新年趣事之红包(区间DP))