问题来源:刘汝佳《算法竞赛入门经典--训练指南》 P61 问题9:

问题描述:有n(n<=15)个城市,两两之间均有道路直接相连,给出每两个城市i和j之间的道路长度L[i][j],求一条经过每个城市一次且仅一次,最后回到起点的路线,使得经过的道路总长度最短(城市编号为0~n-1)。

分析: 1.因为最后走的路线为一个环,可以设城市0为起点城市。

    2.将每个城市看作二进制的一个位(1代表有,0代表没有),则数k可以表示一些城市的集合(例如k=13,二进制表示为1101,表示城市0,2,3的集合),我们可以求得k<=2^15-1,令  aim=2^15-1;

    3.dp[k][j]表示经过了k集合中的所有城市并且以j城市为终点的路径的最小值

    则dp[k][j] = Min{dp[k][j],dp[k-j][i]+dis[i][j] | (0<=i<=n-1 && i属于集合k)};(其中k-j表示集合k中去掉数j后的集合(所以j应该是集合k中的元素)),

例题链接:http://acm.fzu.edu.cn/problem.php?pid=2186

例题: fzu 2186

Problem 2186 小明的迷宫

Accept: 88    Submit: 270
Time Limit: 1000 mSec    Memory Limit : 32768 KB

 Problem Description

小明误入迷宫,塞翁失马焉知非福,原来在迷宫中还藏着一些财宝,小明想获得所有的财宝并离开迷宫。因为小明还是学生,还有家庭作业要做,所以他想尽快获得所有财宝并离开迷宫。

 Input

有多组测试数据。

每组数据第一行给出两个正整数n,m(0<n,m<=100)。代表迷宫的长和宽。

接着n行,每行m个整数。正数代表财宝(财宝的个数不超过10);负数代表墙,无法通过;0代表通道。

每次移动到相邻的格子,所花费的时间是1秒。小明只能按上、下、左、右四个方向移动。

小明的初始位置是(1,1)。迷宫的出口也在(1,1)。

 Output

输出获得所有财宝并逃出迷宫所花费的最小时间,如果无法完成目标则输出-1。

 Sample Input

3 3
0 0 0
0 100 0
0 0 0
2 2
1 1
1 1

 Sample Output

4
4

 Source

FOJ有奖月赛-2015年03月

思路:先将出口和宝藏之间的距离全部通过DFS求出来(出口的地方需要特殊判断和处理),接下来就是裸的TSP问题dp+状压
 #include "stdio.h"
#include "string.h"
#include "queue"
using namespace std;
#define N 105
#define INF 0x3fffffff int m,n;
int map[N][N],mark[N][N];
int dis[][],flag[],dist[];
int dir[][] = {{-,},{,},{,-},{,}}; int dp[][],b[];
int inline Min(int a,int b){ return a<b?a:b; } struct Point
{
int x,y;
} point[]; struct node
{
int x,y;
int length;
}; void DFS(int start,int x,int y,int length)
{
int i,k;
int x1,y1;
queue<node> q;
node cur,next;
cur.x = x;
cur.y = y;
cur.length = ;
q.push(cur);
while(!q.empty())
{
cur = q.front();
q.pop();
for(i=; i<; i++)
{
next.x = x1 = cur.x+dir[i][];
next.y = y1 = cur.y+dir[i][];
next.length = cur.length+;
if(x1<= || x1>n || y1<= || y1>m || mark[x1][y1]!= || map[x1][y1]<)
continue;
if(map[x1][y1]>)
{
k = map[x1][y1];
dis[start][k] = dis[k][start] = next.length;
}
mark[x1][y1] = ;
q.push(next);
}
}
} int main()
{
int ans;
int i,j,k,num,l;
b[] = ;
for(i=; i<; i++) //b[i]存的2^i
b[i] = b[i-]*;
while(scanf("%d %d",&n,&m)!=EOF)
{
num = ;
for(i=; i<=n; ++i)
{
for(j=; j<=m; j++)
{
scanf("%d",&map[i][j]);
if(i== && j==&& map[i][j]>) num--;
if(map[i][j]>) map[i][j]= num++;
else if(map[i][j]<) map[i][j]=-;
}
}
if(map[][]<)
{
printf("-1\n");
continue;
}
map[][] = ;
for(i=; i<=n; ++i)
{
for(j=; j<=m; j++)
{
if(map[i][j]>)
{
k = map[i][j];
point[k].x = i, point[k].y = j;
} }
}
for(i=; i<num; i++)
{
for(j=; j<num; j++)
dis[i][j] = INF;
dis[i][i]= ;
}
for(i=; i<num; i++) //以每个点为起点广搜,求出任意两点间的最短距离
{
memset(mark,,sizeof(mark));
mark[point[i].x][point[i].y] = ;
DFS(i,point[i].x,point[i].y,);
}
num--; //宝藏编号为1~num
int tt = ;
for(i=; i<=num; i++)
{
if(dis[][i]==INF) //只要存在一个INF,表示至少有一个宝藏不可达,输出-1
tt = ;
}
if(tt==)
{
printf("-1\n");
continue;
}
int aim =b[num+]-;//y因为从2^1开始到2^num,则aim = 2^(num+1)-1-2^0
for(i=; i<=aim; i++)
{
for(j=; j<=num; j++)
dp[i][j] = INF;
}
dp[][] = ;
for(l=; l<=aim; l++) //一个集合l
{
for(i=; i<=num; i++)
{
for(j=; j<=num; j++)
{
if(i==j) continue;
if((b[i]&l)==) continue; //必须满足i 在集合l中,不满足,跳过,
if((b[j]&l)==) continue; //必须满足j不在集合l中,不满足,跳过,
if(dp[l][i]==INF) continue;
dp[l|b[j]][j]=Min(dp[l|b[j]][j],dp[l][i]+dis[i][j]);
}
}
}
ans = INF;
for(i=; i<=num; i++)
ans = Min(ans,dp[aim][i]+dis[i][]);
printf("%d\n",ans);
}
return ;
}

07_旅行商问题(TSP问题,货郎担问题,经典NPC难题)的更多相关文章

  1. 【智能算法】用模拟退火(SA, Simulated Annealing)算法解决旅行商问题 (TSP, Traveling Salesman Problem)

    喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 文章声明 此文章部分资料和代码整合自网上,来源太多已经无法查明出处,如侵犯您的权利,请联系我删除. 01 什么是旅行商问题(TS ...

  2. 遗传算法解决旅行商问题(TSP)

    这次的文章是以一份报告的形式贴上来,代码只是简单实现,难免有漏洞,比如循环输入的控制条件,说是要求输入1,只要输入非0就行.希望会帮到以后的同学(*^-^*) 一.问题描述 旅行商问题(Traveli ...

  3. 禁忌搜索算法TSA 旅行商问题TSP python

    import math import random import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot ...

  4. 三进制状态压缩DP(旅行商问题TSP)HDU3001

    http://acm.hdu.edu.cn/showproblem.php?pid=3001 Travelling Time Limit: 6000/3000 MS (Java/Others)     ...

  5. hdu 2224 双调欧几里得旅行商问题tsp

    /* 题意:平面上n个点,确定一条连接各点的最短闭合旅程且每个点仅用一次.这个解的一般形式为NP的(在多项式时间内可以求出) 建议通过只考虑双调旅程(bitonictour)来简化问题,这种旅程即为从 ...

  6. 回溯法 | 旅行商问题(TSP问题)

    学习链接: 回溯法解旅行商问题(TSP).贪心算法:旅行商问题(TSP) 今天早上做了无数个梦,然后被紧紧地吸附在床上.挣扎一番后爬起来,已经是9点了.然后我开始研究旅行商问题. 在一个无向图中找到一 ...

  7. 转载 什么是P问题、NP问题和NPC问题

    原文地址http://www.matrix67.com/blog/archives/105 这或许是众多OIer最大的误区之一.    你会经常看到网上出现“这怎么做,这不是NP问题吗”.“这个只有搜 ...

  8. P问题、NP问题、NPC问题、NP难问题的概念

    P问题.NP问题.NPC问题.NP难问题的概念 离入职尚有几天时间,闲来无事,将大家常见却又很容易搞糊涂的几个概念进行整理,希望对大家有所帮助.你会经常看到网上出现“这怎么做,这不是NP问题吗”.“这 ...

  9. P问题、NP问题和NPC问题

    P问题.NP问题和NPC问题 这或许是众多OIer最大的误区之一.    你会经常看到网上出现“这怎么做,这不是NP问题吗”.“这个只有搜了,这已经被证明是NP问题了”之类的话.你要知道,大多数人此时 ...

随机推荐

  1. Azure开发者任务之一:解决Azure Storage Emulator初始化失败

    初学Windows Azure: 我打算开始学习Windows Azure.我安装了Azure SDK,然后在“Cloud”标签下选择Windows Azure模板,创建了一个项目,然后又创建了一个W ...

  2. c#调用Aspose.Word组件操作word 插入文字/图片/表格 书签替换套打

    由于NPOI暂时没找到书签内容替换功能,所以换用Apose.Word组件. using System; using System.Collections.Generic; using System.C ...

  3. JavaMail入门第三篇 发送邮件

    JavaMail API中定义了一个java.mail.Transport类,它专门用于执行邮件发送任务,这个类的实例对象封装了某种邮件发送协议的底层实施细节,应用程序调用这个类中的方法就可以把Mes ...

  4. 优雅输出Javascript从Chrome浏览器

            一般前端Web开发好的App中js脚本文件,为了节约流量,都会做最小化,甚至合并压缩处理.但在对于需要Debug已处理过Javascript文件就不太方便了,可读性太差了. 使用Goo ...

  5. Windows工作集内存

    Windows任务管理器默认情况下,“内存(私人工作集)”列处于选中状态. 私人工作集是工作集的一个子集,它是描述每个进程所使用的内存数量的技术术语.私人工作集专门描述了某个进程正在使用的且无法与其他 ...

  6. winform(容器、打印、对话框)

    一.布局:2个属性:Anchor:锁定位置Dock:填充位置一般Dock是与容器控件配合使用 二.容器控件:Panel:就是一个区域,类似于DIV,可以独立布局,还可以让其它控件及容器在它的内部再次布 ...

  7. oGrid 介绍如何从 server 取的资料

    接着前次 oGrid 初探,其中有介绍如何操作local 资料,本次介绍如何从 server 取的资料. 依照 MVC 架构原理以及一条小龙本身经验来看,一个好的架构,必须要有着分工明确的设计层次,让 ...

  8. AngularJS directive 指令相关记录

    .... .directive('scopeDemo',function(){ return{ template: "<div class='panel-body'>Name: ...

  9. 浅谈React受控与非受控组件

    背景 React内部分别使用了props, state来区分组件的属性和状态.props用来定义组件外部传进来的属性, 属于那种经过外部定义之后, 组件内部就无法改变.而state维持组件内部的状态更 ...

  10. 移位操作<<和>>,是逻辑数字上的移动(和大端小端无关)

    问题描述 这几天帮同事调试DSP TMS320F28335,这鬼东西蛋疼死了.char是16bit的,16位就是他的最小内存单元.但是PC机串口发过来的有8bit的数据,然后转换就出问题. 一开始不知 ...