1. 程式人生 > >vijos 1069 新年趣事之紅包(區間DP)

vijos 1069 新年趣事之紅包(區間DP)

題意:給你一個凸包,問遍歷所有點一遍的最短路徑

分析:由於圖形是一個凸包,所以肯定是選一個點,然後從兩端不斷拓展出去,假設已經拓展[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;
}