题目: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; }