zoukankan      html  css  js  c++  java
  • 紫书 例题 9-3 UVa 1347 ( 状态设计)

    首先做一个转化,这种转化很常见。
    题目里面讲要来回走一遍,所以就转化成两个从起点到终点,路径不重合
    那么很容易想到用f[i][j]表示第一个走到i,第二个人走到j还需要走的距离
    但是这里无法保证路径不重合,所以这里怎么设计状态很关键。
    我们设f[i][j]是1到max(i, j)全部走过,同时第一个在i,第二人在j,
    还需要走的距离,可以看出f[i][j] = f[j][i],所以我们可以规定i > j
    那么这么规定有什么好处呢?我们可以让两个人走的路径是1, 2, 3, 4……
    换句话说,当前是f[i][j],根据定义,1到i全部走过,接下来要走到第i+1个位置
    假设是第一个人走,也就是在i的这个人走,那么可以从f[i][j]转移到f[i+1][j]
    假设是第二个人走,也就是在j的这个人走,那么可以从f[i][j]转移到f[i+1][i](j到i+1,而规定前面的要大)
    dist[i][j]表示i到j的欧几里得距离
    边界是f[n-1][j] = dist[i][n] + dist[j][n]最后的时候肯定是两个人走到终点,我们要从终点逆推
    最终答案是d[2][1] + dist[2][1]。

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #define REP(i, a, b) for(int i = (a); i < (b); i++)
    using namespace std;
    
    const int MAXN = 55;
    double x[MAXN], y[MAXN], dist[MAXN][MAXN], d[MAXN][MAXN];
    
    int main()
    {
    	int n;
    	while(~scanf("%d", &n))
    	{
    		REP(i, 1, n + 1) scanf("%lf%lf", &x[i], &y[i]);
    		REP(i, 1, n + 1)
    			REP(j, 1, n + 1)
    				dist[i][j] = sqrt(pow(x[i]-x[j], 2) + pow(y[i]-y[j], 2));
    		
    		for(int i = 2; i <= n; i++)
    			REP(j, 1, i)
    			{
    				if(i == 2) d[i][j] = dist[1][2];
    				else d[i][j] = min(d[i+1][j] + dist[i][i+1], d[i+1][i] + dist[i+1][j]);
    			}
    		printf("%.2lf
    ", d[2][1] + dist[2][1]);
    	}
    	return 0;
    }
  • 相关阅读:
    Windows 配置JAVA的环境变量
    不直接用NSLog
    Mongodb for Mac 安装
    Redis Mac 安装及简单命令使用
    第十五天和十六天学习笔记
    第十四天学习笔记
    第十三天学习笔记
    第十二天学习笔记
    第十一天学习笔记
    第十天学习笔记
  • 原文地址:https://www.cnblogs.com/sugewud/p/9819459.html
Copyright © 2011-2022 走看看