【紫書】(UVa1347)Tour
阿新 • • 發佈:2019-02-01
繼續考慮dp題目。
題意分析
其實這裡只是更加仔細的做一個lrj的復讀機(Orz
他分析了一個很重要的結果:如果是一個人從左到右再回來,並且每個點恰經過一次,那麼等價於兩個人從左到右每個點經過一次地遍歷這些點。因為這樣,我們才能夠得到
但是這樣也不夠。
因此,我們定義成這樣:把原來的狀態表示成 (i,j)=d(j,i)
這樣會不會漏解呢?不會。如果i能夠直接走到i+2,那麼根據定義就無法走到i+1了。因此,我們讓j走到i+1,是能夠做到不遺漏的——因為我們之前考慮的情況不存在。
從上面不是我的分析可以看出,一個對題目深入分析得到的狀態對dp題目的解決多麼重要。
程式碼
很神祕,我用記憶化搜尋寫了半天,tle了六次……可能真的是有效率問題。以我現在的水平搞不明白是怎麼回事,以後再解決吧。但是這裡用迴圈不困難。
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <queue>
#include <set>
#include <iomanip>
#include <vector>
#define ZERO(x) memset((x),0,sizeof(x))
using namespace std;
//const int maxn=;
int x[1005 ],y[1005];
double dp[1005][1005];
double dist[1005][1005];
double inf;
int n;
int main()
{
while(scanf("%d",&n)==1)
{
memset(dp,0x43,sizeof(dp));
inf=dp[0][0];
for(int i=1;i<=n;++i)
scanf("%d%d",&x[i],&y[i]);
for(int i=1;i<=n;++i)
for(int j=1;j<i;++j)
dist[j][i]=dist[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
for(int i=n-1;i>=1;--i)
for(int j=1;j<i;++j)
if(i==n-1) dp[i][j]=dist[i][n]+dist[j][n];
else dp[i][j]=min(dp[i+1][j]+dist[i][i+1],dp[i+1][i]+dist[i+1][j]);
printf("%.2lf\n",dp[2][1]+dist[1][2]);
}
return 0;
}