UVA

来源:互联网 发布:win10视频剪辑软件 编辑:程序博客网 时间:2024/06/07 13:14

题意:

给按x大小给定一些x值不同的点,问从最左边走到最右边再走回来,每个点走一遍,形成一个环,最短路径是多少


思路:

我们可以确定的是左右断点是确定的,我本来想的是,对于点来说,分到上下方的,,再往下就不知道了


后来看紫书才知道:一个状态量 dp[ i ] [ j ] 表示前第 i j 两个点(包括之前的点)走完以后,到第n个点的最短距离

过程包括:

边界:第 n-1 个点和另外的点作为边界的状态到 最后n的距离;

转移:dp[i][j] -> dp[i+1][j] 或者 dp[i+1][i](这个等价于 dp[i][i+1] ) 分别是 i 走到 i+1 ,和 j 走到 i+1;

因为整个题 解决都是 dp[i][j]  表示的都是 i > j 的,只能用 dp[ i +1] [i] ;



#include<iostream>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<cmath>#include<set>#include<queue>#include<stack>#include<map>#define PI acos(-1.0)#define in freopen("in.txt", "r", stdin)#define out freopen("out.txt", "w", stdout)#define kuaidian ios::sync_with_stdio(0);using namespace std;typedef long long ll;typedef unsigned long long ull;const int maxn = 1000 + 7, maxd = 1e8;const ll mod = 1e9 + 7;const int INF = 0x7f7f7f7f;int n;double x[maxn], y[maxn];double len[maxn][maxn], dp[maxn][maxn];void init() {    for(int i = 1; i <= n; ++i) {        scanf("%lf %lf", &x[i], &y[i]);    }    for(int i = 1; i <= n; ++i) {        for(int j = 1; j <= n; ++j) {            len[i][j] = sqrt( (fabs(x[i]-x[j])*fabs(x[i]-x[j])) + (fabs(y[i]-y[j])*fabs(y[i]-y[j])) );            //cout << len[i][j] << " ";        }        //cout << endl;    }    //cout << endl;    //memset(dp, INF, sizeof dp);}void solve() {    for(int i = 1; i <= n-2; ++i) {        dp[n-1][i] = len[i][n] + len[n-1][n];    }    for(int i = n-2; i > 0; --i) {        for(int j = 1; j < i; ++j) {            dp[i][j] = min( dp[i+1][j]+len[i][i+1], dp[i+1][i]+len[j][i+1] );        }    }//    for(int i = 1; i <= n; ++i) {//        cout << i << " : ";//        for(int j = 1; j <= n; ++j) {//            cout << dp[i][j] << " ";//        }//        cout << endl;//    }    printf("%.2f\n", len[1][2] + dp[2][1]);    //cout  <<  << len[1][2] + dp[2][1] << endl;}int main() {    while( ~scanf("%d", &n) && n ) {        init();        solve();    }    return 0;}


原创粉丝点击