问题来源:刘汝佳《算法竞赛入门经典--训练指南》 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. WampServer 给电脑搭建apache服务器和php环境

    WampServer 给电脑搭建apache服务器和php环境 前端不仅要做页面展示层,还负责着数据交互的部分,不要等到后端人员做好工作了前端才开始对接,那样太被动了. 前端在完成静态页面的编码后,就 ...

  2. 改造一下C# Substring()函数

    C#的Substring()函数中,如果我们一不小心输入一个截取长度大于字符串的长时,就会收到一个异常:startIndex cannot be larger than length of strin ...

  3. c# winForm 等待窗体的实现

    最近在做一个项目,需要用到等待窗体,在DevExpress下面有SplashScreen控件可以使用,同时也有ProgressIndicator控件能用,但是如果没有用Dev开发的话,我们就需要自定义 ...

  4. MSIL指令集

    名称 说明 Add 将两个值相加并将结果推送到计算堆栈上. Add.Ovf 将两个整数相加,执行溢出检查,并且将结果推送到计算堆栈上. Add.Ovf.Un 将两个无符号整数值相加,执行溢出检查,并且 ...

  5. 雷军V5,米3横空出世

    小米3 下午两点,小米CEO:雷军(也是一个传奇人物),虽然没购买门票,只是自己一个人看微博,看新闻,还是了解到了小米3的面貌,这次雷哥还给大家带来了MITV,售价¥2999!(无法相信)顶配.这次我 ...

  6. HDU 2577---How to Type

    HDU  2577 Description Pirates have finished developing the typing software. He called Cathy to test ...

  7. transfer between javabean and map

    1. java bean 转化成 map import java.beans.BeanInfo; import java.beans.Introspector; import java.beans.P ...

  8. Follow me to learn what is repository pattern

    Introduction Creating a generic repository pattern in an mvc application with entity framework is th ...

  9. mysql内存消耗分析

    最近有些生产服务器老是mysql内存不停得往上涨,开发人员和维护反馈,用了不少的临时表,问题时常线上发生,测试又一直比较难重现. 经观察mysql内存的os占用趋势,发现从8:40开始,mysql内存 ...

  10. SQL对字符串数组的处理

    一,用临时表作为数组 复制代码代码如下: create function f_split(@c varchar(2000),@split varchar(2)) returns @t table(co ...