07_旅行商问题(TSP问题,货郎担问题,经典NPC难题)
问题来源:刘汝佳《算法竞赛入门经典--训练指南》 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
Sample Output
Source
FOJ有奖月赛-2015年03月
- #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难题)的更多相关文章
- 【智能算法】用模拟退火(SA, Simulated Annealing)算法解决旅行商问题 (TSP, Traveling Salesman Problem)
喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 文章声明 此文章部分资料和代码整合自网上,来源太多已经无法查明出处,如侵犯您的权利,请联系我删除. 01 什么是旅行商问题(TS ...
- 遗传算法解决旅行商问题(TSP)
这次的文章是以一份报告的形式贴上来,代码只是简单实现,难免有漏洞,比如循环输入的控制条件,说是要求输入1,只要输入非0就行.希望会帮到以后的同学(*^-^*) 一.问题描述 旅行商问题(Traveli ...
- 禁忌搜索算法TSA 旅行商问题TSP python
import math import random import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot ...
- 三进制状态压缩DP(旅行商问题TSP)HDU3001
http://acm.hdu.edu.cn/showproblem.php?pid=3001 Travelling Time Limit: 6000/3000 MS (Java/Others) ...
- hdu 2224 双调欧几里得旅行商问题tsp
/* 题意:平面上n个点,确定一条连接各点的最短闭合旅程且每个点仅用一次.这个解的一般形式为NP的(在多项式时间内可以求出) 建议通过只考虑双调旅程(bitonictour)来简化问题,这种旅程即为从 ...
- 回溯法 | 旅行商问题(TSP问题)
学习链接: 回溯法解旅行商问题(TSP).贪心算法:旅行商问题(TSP) 今天早上做了无数个梦,然后被紧紧地吸附在床上.挣扎一番后爬起来,已经是9点了.然后我开始研究旅行商问题. 在一个无向图中找到一 ...
- 转载 什么是P问题、NP问题和NPC问题
原文地址http://www.matrix67.com/blog/archives/105 这或许是众多OIer最大的误区之一. 你会经常看到网上出现“这怎么做,这不是NP问题吗”.“这个只有搜 ...
- P问题、NP问题、NPC问题、NP难问题的概念
P问题.NP问题.NPC问题.NP难问题的概念 离入职尚有几天时间,闲来无事,将大家常见却又很容易搞糊涂的几个概念进行整理,希望对大家有所帮助.你会经常看到网上出现“这怎么做,这不是NP问题吗”.“这 ...
- P问题、NP问题和NPC问题
P问题.NP问题和NPC问题 这或许是众多OIer最大的误区之一. 你会经常看到网上出现“这怎么做,这不是NP问题吗”.“这个只有搜了,这已经被证明是NP问题了”之类的话.你要知道,大多数人此时 ...
随机推荐
- 从零开始,CentOS6安装ghost博客
买了个Bandwagon的VPS来科学上网的,寻思着空间还大顺便做个博客呗. 然后就安装了AMH面板,再搞了个wordpress博客玩玩. 接触到Ghost博客的时候,心血来潮想装一个. 然后就试着搞 ...
- 【循序渐进学Python】13.基本的文件I/O
文件I/O是Python中最重要的技术之一,在Python中对文件进行I/O操作是非常简单的. 1. 打开文件 使用 open 函数来打开文件,语法如下: open(name[, mode[, buf ...
- strtr对用户输入的敏感词汇进行过滤
/** * 过滤用户输入的基本数据,防止script攻击 * * @access public * @return string */ function compile_str($str) { $ar ...
- 【转载】NodeJS、NPM安装配置步骤(windows版本)
1.windows下的NodeJS安装是比较方便的(v0.6.0版本之后,支持windows native),只需要登陆官网(http://nodejs.org/),便可以看到首页的“INSTALL” ...
- mybatis generator with oracle
1.generator.xml <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE generat ...
- 机器学习实战 - 读书笔记(13) - 利用PCA来简化数据
前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第13章 - 利用PCA来简化数据. 这里介绍,机器学习中的降维技术,可简化样品数据. ...
- python3学习笔记目录
目录: Python基础(一),Day1 python基础(二),Day2 python函数和常用模块(一),Day3 python函数和常用模块(二),Day4 python函数和常用模块(三),D ...
- Oracle 中 call 和 exec的区别
今天发现了一个小东西,觉得很有意思,查找了一些资料,跟大家分享一下: 在sqlplus中: 在第三方提供的工具(如:plsqldev) 总结: exec是sqlplus的命令,只能在sqlplus中使 ...
- Incorrect string value: '\xF0\x90\x8D\x83...' for column 通用解决方案
mysql插入非ascii字符时报这个错的根本原因在于: 对应表的字符集无法存储要插入的字符,比如汉字插入latin1编码,某些特殊字符插入gbk或者utf8等. 检查一下实际插入的字符以及对应表或者 ...
- java随机生成指定的位数
/** * 获取count个随机数 * @param count 随机数个数 * @return */ public static String game(int count){ StringBuff ...