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 ...
随机推荐
- springmvc 配置和spring配置?
最近在接触mybatis,之间使用springmvc时,配置文件一直是,web.xml+XX-servlet.xml 的配置(xx为web.xml中servlet name名称).为了整合mybati ...
- .Net4.0并行库介绍——Cancellation Framework
在.net 4.0中,引入了一个新的类CancellationToken,这个类基本上集成了我们各种常用的取消方式,在并发任务中非常有用. 同步模式下的取消: 一种比较常见的需要支持取消功能的的是一些 ...
- 关于ReactiveCocoa的实际用法
监听UITextView控件 text属性 @weakify(self); [self.textViewAdvice.rac_textSignal subscribeNext:^(NSString * ...
- 仿LOL项目开发第二天
仿LOL项目开发第二天 by草帽 接着上节来讲,上节更新还没开始写代码逻辑,今天我们补充完整. 我们找到VersionManager脚本里面的CheckVersion方法: 首先我们想到检测版本,需要 ...
- php 方法笔记 比file_get_contents好
/*比file_get_contents稳定的多!$timeout为超时时间,单位是秒,默认为1s.*/ private function curl_get_contents($url,$timeou ...
- 关于JDBC PreparedStatement
PreparedStatement的执行步骤: 1. 向数据库服务器发送SQL语句,数据库对SQL进行解析和优化(conn.preparedStatement(sql)) 2. 向数据库发送绑定的参数 ...
- 1644 免费馅饼 题解(c++)
1644 免费馅饼(巴蜀oj上的编号) 题面: SERKOI最新推出了一种叫做"免费馅饼"的游戏. 游戏在一个舞台上进行.舞台的宽度为W格,天幕的 ...
- Android -- Vibrator
Vibrator public c ...
- 【云计算】使用docker搭建nfs实现容器间共享文件
首先介绍下今天的两个主角:nfs和docker nfs 是什么 NFS(Network File System)即网络文件系统,是FreeBSD支持的文件系统中的一种,它允许网络中的计算机之间通过TC ...
- CSS3-border-radius 属性
向 div 元素添加圆角边框: div { border:2px solid; border-radius:25px; } IE9+.Firefox 4+.Chrome.Safari 5+ 以及 Op ...