题意:

给定一系列按x坐标升序排列的点,一个人从左向右走到终点再从终点走回起点,要求每个点恰好经过一次,问所走过的最短路径长度。

分析:

可以看成是两个人同时从起点向终点走,且除起点终点外每个点恰有一个人经过。

John uses the following strategy: he starts from the leftmost point, then he goes strictly left to right to the rightmost point, and then he goes strictly right back to the starting point.

用d[i][j]表示一个人走到第i个位置,另一个人走到第j个位置时,已经共走了多少距离,规定其中i>j,且1~i全部走过。

题目要求严格按照从左到右和从右到左的顺序,所以不管哪个人下一步只能走i+1,i+2….如果一个人跳过i+1直接走到了i+2,则i+1必将由另一个人走,不妨让走i+1的人先走,这样便保证每次都先走到i+1,得到状态转移方程:(dist数组保存两点之间距离)

dp[i+1][j]=min(dp[i+1][j],dp[i][j]+dist[i+1][i]);
dp[i+1][i]=min(dp[i+1][i],dp[i][j]+dist[i+1][j]);

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=55, INF = 0x3fffffff; //为什么是55?
double x[maxn],y[maxn],dist[maxn][maxn],dp[maxn][maxn];
int main(void)
{
int n;
while(scanf("%d",&n) == 1){
for(int i =0; i < n ; i++)
scanf("%lf%lf",&x[i], &y[i]);
for(int i = 0;i < n; i++)
for(int j = 0 ; j < n ; j++)
dist[i][j] = sqrt((x[i] - x[j]) * (x[i]-x[j]) + (y[i] - y[j]) * (y[i] - y[j])); for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++)
dp[i][j] = INF;
}
dp[1][0]=dist[1][0]; for(int i = 1; i < n - 1; i++) {
for(int j = 0; j < i; j++){
dp[i + 1][j] = min(dp[i + 1][j], dp[i][j] + dist[i + 1][i]);
dp[i + 1][i] = min(dp[i + 1][i], dp[i][j] + dist[i + 1][j]);
}
} double ans = INF;
for(int i = 0; i < n - 1; i++){
ans = min(ans, dp[n-1][i] + dist[n - 1][i]); }
printf("%.2lf\n", ans);
}
return 0;
}

还可以用d[i][j]表示一个人走到第i个位置,另一个人走到第j个位置时,还剩多少距离,则状态转移方程

dp[i][j]=min(dist[i][i+1]+dp[i+1][j],dist[j][i+1]+dp[i+1][i]);  

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=55, INF = 0x3fffffff; //为什么是55?
double x[maxn],y[maxn],dist[maxn][maxn],dp[maxn][maxn];
int main(void)
{
int n;
while(scanf("%d",&n) == 1){
for(int i =0; i < n ; i++)
scanf("%lf%lf",&x[i],&y[i]);
for(int i = 0;i < n; i++)
for(int j = 0 ; j < n ; j++)
dist[i][j] = sqrt((x[i] - x[j]) * (x[i]-x[j]) + (y[i] - y[j]) * (y[i] - y[j])); for(int i = n - 2; i >=1; i--) {
for(int j = i - 1; j >= 0; j--){
if(i == n - 2) dp[i][j] = dist[i][n - 1] + dist[j][n - 1];
else
dp[i][j] = min(dist[i][i + 1]+dp[i + 1][j], dist[j][i + 1] + dp[i + 1][i]);
}
}
printf("%.2lf\n", dist[0][1] + dp[1][0]);
}
return 0;
}

貌似叫双调旅行商问题?

UVA 1347_Tour的更多相关文章

  1. uva 1354 Mobile Computing ——yhx

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABGcAAANuCAYAAAC7f2QuAAAgAElEQVR4nOy9XUhjWbo3vu72RRgkF5

  2. UVA 10564 Paths through the Hourglass[DP 打印]

    UVA - 10564 Paths through the Hourglass 题意: 要求从第一层走到最下面一层,只能往左下或右下走 问有多少条路径之和刚好等于S? 如果有的话,输出字典序最小的路径 ...

  3. UVA 11404 Palindromic Subsequence[DP LCS 打印]

    UVA - 11404 Palindromic Subsequence 题意:一个字符串,删去0个或多个字符,输出字典序最小且最长的回文字符串 不要求路径区间DP都可以做 然而要字典序最小 倒过来求L ...

  4. UVA&&POJ离散概率与数学期望入门练习[4]

    POJ3869 Headshot 题意:给出左轮手枪的子弹序列,打了一枪没子弹,要使下一枪也没子弹概率最大应该rotate还是shoot 条件概率,|00|/(|00|+|01|)和|0|/n谁大的问 ...

  5. UVA计数方法练习[3]

    UVA - 11538 Chess Queen 题意:n*m放置两个互相攻击的后的方案数 分开讨论行 列 两条对角线 一个求和式 可以化简后计算 // // main.cpp // uva11538 ...

  6. UVA数学入门训练Round1[6]

    UVA - 11388 GCD LCM 题意:输入g和l,找到a和b,gcd(a,b)=g,lacm(a,b)=l,a<b且a最小 g不能整除l时无解,否则一定g,l最小 #include &l ...

  7. UVA - 1625 Color Length[序列DP 代价计算技巧]

    UVA - 1625 Color Length   白书 很明显f[i][j]表示第一个取到i第二个取到j的代价 问题在于代价的计算,并不知道每种颜色的开始和结束   和模拟赛那道环形DP很想,计算这 ...

  8. UVA - 10375 Choose and divide[唯一分解定理]

    UVA - 10375 Choose and divide Choose and divide Time Limit: 1000MS   Memory Limit: 65536K Total Subm ...

  9. UVA - 11584 Partitioning by Palindromes[序列DP]

    UVA - 11584 Partitioning by Palindromes We say a sequence of char- acters is a palindrome if it is t ...

随机推荐

  1. Neither BindingResult nor plain target object for bean name 'user' available as request attribute

    这个异常是因为jsp页面写错了. 把<form:form></form:form>标签改成普通的标签即可. 应该是第一次访问的时候,user是空的.但springmvc不能是空 ...

  2. 面相切面编程AOP以及在Unity中的实现

    一.AOP概念 AOP(Aspect-Oriented Programming,面向切面的编程),它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术.它是 ...

  3. Elasticsearch--集群&时光之门和恢复控制

    节点发现 启动一个Elasticsearch节点时,该节点会开始寻找具有相同集群名字并且可见的主节点.如果找到主节点,该节点加入一个已经组成了的集群:如果没有找到,该节点成为主节点(如果配置允许).形 ...

  4. 最近面试oracle 数据库的知识点

    1. Oracle跟SQL Server 2005的区别? 宏观上: 1). 最大的区别在于平台,oracle可以运行在不同的平台上,sql server只能运行在windows平台上,由于windo ...

  5. 原生jsonp跨域

    <script> // jsonp跨域原生写法 var script = document.createElement('script'); script.src = 'http://19 ...

  6. 玩转CPU运行曲线

    Leaf 是不是从来没有想过看看cpu运行曲线啊骚年?顶多也就仅仅是看看cpu利用率,吓自己一跳后感觉关闭几个不该打开的程序~ 然而问题来了,微软公司要让你绘制cpu运行曲线啊!!不仅是固定的直线,还 ...

  7. System.Web.Optimization找不到引用怎么办

    新建Bootstap for MVC5出现的问题, 通过打开VS 工具->NUGET程序包管理器->控制台 输入以下命令进行完成,一切完成 Install-Package Microsof ...

  8. day25-1 网络架构与互联网组成

    目录 网络架构 单机架构 CS架构 数据放在服务端和客户端的利与弊 BS架构 互联网和互联网的组成 互联网的硬件组成 互联网的软件组成 网络架构 单机架构 应用领域: 单机游戏 CS架构 基于网络,应 ...

  9. apm - 查询高级电源管理(APM) BIOS

    总览 apm [ - vVmsS ] 描述 apm 读取 /proc/apm 并用人能看懂的格式输出.因为提供了首要的电池状态,这个命令在有兼容的 APM BIOS 的笔记本电脑上非常有用. apm ...

  10. MFC如何设置窗口最前

    首先,放到最前 this->SetWindowPos(&wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);//使窗口总是在最前面 this->Se ...