POJ 2677 旅行商问题 双调dp或者费用流
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 3408 | Accepted: 1513 |
Description
is represented by a point in the plane pi = < xi,yi >. 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. It is known
that the points have distinct x-coordinates.
Write a program that, given a set of n points in the plane, computes the shortest closed tour that connects the points according to John's strategy.
Input
White spaces can occur freely in input. The input data are correct.
Output
is in the table below. Here there are two data sets. The first one contains 3 points specified by their x and y coordinates. The second point, for example, has the x coordinate 2, and the y coordinate 3. The result for each data set is the tour length, (6.47
for the first data set in the given example).
Sample Input
3
1 1
2 3
3 1
4
1 1
2 3
3 1
4 2
Sample Output
一旅行商从左向右走到最右边,然后再返回原来出发点的最短路径。
两种做法,第一种dp。dp[i][j]表示以i。j结尾的两条不相交的路径如果i一定大于j。i有两种选择,与i-1相连。不与i-1相连,然后dp
代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <math.h>
#include <queue>
#include <set>
#include <algorithm>
#include <stdlib.h>
using namespace std;
#define ll int
#define N 1005
#define inf 100000000
struct node{
double x, y;
bool operator<(const node&a)const{
if(a.x==x)return a.y>y;
return a.x>x;
}
}p[N];
double Dis(node a, node b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
int n;
double dis[N][N],dp[N][N];
int main(){
ll i, j, u, v;
while(~scanf("%d",&n)){//dp[i][j]表示以i。j为结尾的两条不相交的路径
for(i=1;i<=n;i++)scanf("%lf %lf",&p[i].x,&p[i].y);
sort(p+1,p+n+1);
for(i=1;i<=n;i++)for(j=1;j<=n;j++)dis[i][j] = Dis(p[i],p[j]), dp[i][j] = inf; dp[1][1] = 0;
for(i=2;i<=n;i++)
{
for(j = 1;j < i; j++)
{
dp[i][j] = min(dp[i-1][j]+dis[i][i-1], dp[i][j]);//i不与i-1相连,
dp[i][i-1] = min(dp[i-1][j]+dis[j][i], dp[i][i-1]);//i与i-1相连。
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)cout<<dp[i][j]<<" ";
cout<<endl;
}
printf("%.2lf\n",dp[n][n-1]+dis[n][n-1]);
}
return 0;
}
费用流,把每个点拆点,中间连流量为1,费用为负无穷的边。代表该点必须选择,两两之间连流量为1,费用为两点距离的边,起点,终点连边,流量为1,费用为0.
代表能够增广两次。
代码:
/* ***********************************************
Author :_rabbit
Created Time :2014/5/17 9:42:51
File Name :6.cpp
************************************************ */
#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <string>
#include <time.h>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define INF 1001000
#define eps 1e-8
#define pi acos(-1.0)
typedef long long ll;
const int maxn=4010;
const int maxm=200000;
struct Edge{
int next,to,cap;
double cost;
Edge(int _next=0,int _to=0,int _cap=0,double _cost=0){
next=_next;to=_to;cap=_cap;cost=_cost;
}
}edge[maxm];
int head[maxn],vis[maxn],pre[maxn],n,tol;
double dis[maxn];
void addedge(int u,int v,int cap,double cost){
edge[tol]=Edge(head[u],v,cap,cost);head[u]=tol++;
edge[tol]=Edge(head[v],u,0,-cost);head[v]=tol++;
}
bool spfa(int s,int t){
queue<int> q;
for(int i=0;i<=n;i++)
dis[i]=INF,vis[i]=0,pre[i]=-1;
dis[s]=0;vis[s]=1;q.push(s);
while(!q.empty()){
int u=q.front();q.pop();vis[u]=0;
// cout<<"u="<<u<<" "<<dis[u]<<endl;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(edge[i].cap>0&&dis[v]>dis[u]+edge[i].cost){
dis[v]=dis[u]+edge[i].cost;
pre[v]=i;
if(!vis[v])vis[v]=1,q.push(v);
}
}
}
if(pre[t]==-1)return 0;
return 1;
}
void fun(int s,int t,int &flow,double &cost){
flow=0;cost=0;
while(spfa(s,t)){
int MIN=INF;
for(int i=pre[t];i!=-1;i=pre[edge[i^1].to])
if(MIN>edge[i].cap)MIN=edge[i].cap;
for(int i=pre[t];i!=-1;i=pre[edge[i^1].to])
edge[i].cap-=MIN,edge[i^1].cap+=MIN,cost+=edge[i].cost*MIN;
flow+=MIN;
}
}
struct Point{
double x,y;
}pp[10000];
double dist(Point a,Point b){
double ss=a.x-b.x;
double tt=a.y-b.y;
return sqrt(ss*ss+tt*tt);
}
int main(){
int m;
// freopen("data.out","w",stdout);
while(cin>>m){
memset(head,-1,sizeof(head));tol=0;
for(int i=1;i<=m;i++)cin>>pp[i].x>>pp[i].y;
for(int i=1;i<=m;i++){
for(int j=i+1;j<=m;j++){
double dd=dist(pp[i],pp[j]);
addedge(i+m,j,1,dd);
}
addedge(i,i+m,1,-INF);
}
addedge(1,m+1,1,0);
addedge(m,2*m,1,0);
n=2*m;
int flow;double cost;
fun(1,2*m,flow,cost);
printf("%.2lf\n",cost+m*INF);
}
return 0;
}
POJ 2677 旅行商问题 双调dp或者费用流的更多相关文章
- POJ 3686 The Windy's (费用流)
[题目链接] http://poj.org/problem?id=3686 [题目大意] 每个工厂对于每种玩具的加工时间都是不同的, 并且在加工完一种玩具之后才能加工另一种,现在求加工完每种玩具的平均 ...
- BZOJ 2424 DP OR 费用流
思路: 1.DP f[i][j]表示第i个月的月底 还剩j的容量 转移还是相对比较好想的-- f[i][j+1]=min(f[i][j+1],f[i][j]+d[i]); if(j>=u[i+1 ...
- luogu P5470 [NOI2019]序列 dp 贪心 费用流 模拟费用流
LINK:序列 考虑前20分 容易想到爆搜. 考虑dp 容易设\(f_{i,j,k,l}\)表示前i个位置 选了j对 且此时A选择了k个 B选择了l个的最大值.期望得分28. code //#incl ...
- [CF1525D] Armchairs (DP / 模拟费用流)
题面简述 一条线上等距地分布着 n n n 老鼠和 m m m 洞( m ≥ n m\geq n m≥n),这连续 n + m n+m n+m 个位置上要么是老鼠要么是洞,一个老鼠进一个洞,代价是所有 ...
- poj 3422 Kaka's Matrix Travels 费用流
题目链接 给一个n*n的矩阵, 从左上角出发, 走到右下角, 然后在返回左上角,这样算两次. 一共重复k次, 每个格子有值, 问能够取得的最大值是多少, 一个格子的值只能取一次, 取完后变为0. 费用 ...
- POJ 2175:Evacuation Plan(费用流消圈算法)***
http://poj.org/problem?id=2175 题意:有n个楼,m个防空洞,每个楼有一个坐标和一个人数B,每个防空洞有一个坐标和容纳量C,从楼到防空洞需要的时间是其曼哈顿距离+1,现在给 ...
- 【BZOJ-4213】贪吃蛇 有上下界的费用流
4213: 贪吃蛇 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 58 Solved: 24[Submit][Status][Discuss] Desc ...
- 洛谷 1004 dp或最大费用流
思路: dp方法: 设dp[i][j][k][l]为两条没有交叉的路径分别走到(i,j)和(k,l)处最大价值. 则转移方程为 dp[i][j][k][l]=max(dp[i-1][j][k-1][l ...
- POJ 2175 Evacuation Plan (费用流,负环,消圈法,SPFA)
http://poj.org/problem?id=2175 Evacuation Plan Time Limit: 1000MS Memory Limit: 65536K Total Submi ...
随机推荐
- crtmpserver配置文件详解
Configuration file配置文件 The configuration file is actually a lua script which must contain an object ...
- Talairach空间、MNI空间、Native空间、Stereotaxic空间
Talairach空间.MNI空间.Native空间.Stereotaxic空间 Native空间就是原始空间. 图像没有做任何变换时就是在原始空间.在这个空间中图像的维度.原点.voxel size ...
- .a 库文件信息查看
在Linux 下经常需要链接一些 *.a的库文件,那怎么查看这些*.a 中包 含哪些文件.函数.变量: 1. 查看文件:ar -t *.a 2. 查看函数.变量:nm *.a
- 分享一个基于 Node.js 的 Web 开发框架 - Nokitjs
简介 Nokit 是一个简单易用的基于 Nodejs 的 Web 开发框架,默认提供了 MVC / NSP / RESTful 等支持,并提供对应项目模板.管理工具. 资源 GitHub https: ...
- [Android UI] listview 自定义style
<style name="comm_listview_style"> <item name="android:cacheColorHint"& ...
- iOS:ASIHttpRequest虽不更新,但仍值得详细了解
一.使用ASIHTTPRequest可以很方便的进行一下操作:同步/异步方式下载数据,定义下载队列,让队列中的任务按指定的并发数来下载(队列下载必须是异步的),提交表单,文件上传,处理cookie,设 ...
- Java中Action层、Service层、Modle层和Dao层的功能区分
一.Java中Action层.Service层.Modle层和Dao层的功能区分: 首先,这是现在最基本的分层方式,结合了SSH架构. modle层就是对应的数据库表的实体类.(即domain) Da ...
- ORA-00600 qerpxInitialize
今天早上巡检又见bug: A select query using a connect-by clause executing using parallel query may fail with O ...
- (顺序表应用5.1.1)POJ 3750 小孩报数问题(基本的约瑟夫环问题:给出人数n,出发位置w,间隔数s)
/* * POJ_3750.cpp * * Created on: 2013年10月30日 * Author: Administrator */ #include <iostream> # ...
- js 构造函数(construction)与原型(prototype)
1.面向对象:js原型 java有class和instance,js仅仅有构造函数(function Cat(name,age){this.name=name;this.age=age}),为了实现数 ...