最短路+状态压缩dp(旅行商问题)hdu-4568-Hunter
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4568
题目大意:
给一个矩阵 n*m (n m<=200),方格里如果是0~9表示通过它时要花费的代价,-1表示不能通过它。
矩阵中有k(k<=13)个珠宝,问从任意外边框出发取走所有珠宝并求走出矩阵的最小的代价。
解题思路:
先dij预处理每一个珠宝到其他其他珠宝的最小花费,不包括自己的花费。然后就是裸的TSP问题了,状态压缩dp即可。
dp[i][j]表示最后到达第i个珠宝,且访问珠宝的状态为j时,最小的花费。
dd[i][j]表示珠宝i到珠宝j之间的花费,注意此时包括j的花费不包括i的花费。
对于已求出的每一种珠宝状态更新后面未求出珠宝的状态。
代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF 0x1f1f1f1f
#define PI acos(-1.0)
#define ll __int64
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std; /*
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
*/
struct Node
{
int id,dis;
//Node(){}
Node(int x,int y)
{
id=x,dis=y;
}
friend bool operator <(const struct Node &a,const struct Node &b)
{
return a.dis>b.dis; //按距离从小到达排序,便于优先队列找到距离当前宝藏的最小距离
}
};
#define Maxn 220
int dd[20][20];//两个宝藏之间的距离
int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
int istr[Maxn][Maxn]; //表示珠宝的标号
int sa[Maxn][Maxn],cost[20];//cost[i]表示i宝藏到边界的最短距离
int n,m,k,hash[20],dp[20][1<<15]; int tmpdis[Maxn*Maxn];//其他宝藏距离当前宝藏的距离
bool vis[Maxn][Maxn]; bool isbor(int x,int y) //是否为边界
{
if(x==0||x==n-1||y==0||y==m-1)
return true;
return false;
} bool iscan(int x,int y) //是否在矩阵内部
{
if(x<0||x>=n||y<0||y>=m)
return false;
return true;
} void dij(int hh,int cur) //迪杰斯特拉算法求
{
memset(tmpdis,INF,sizeof(tmpdis));
memset(vis,false,sizeof(vis));
vis[hh/m][hh%m]=true; priority_queue<Node>myq;
tmpdis[hh]=0;
myq.push(Node(hh,0)); while(!myq.empty())
{
Node tmp=myq.top(); //把距离当前宝藏距离最小的位置找到
myq.pop(); int tt=tmp.id;
int x=tt/m,y=tt%m; if(isbor(x,y)) //如果是边界,更新边界
cost[cur]=min(cost[cur],tmp.dis);
if(istr[x][y]!=-1) //如果是其他珠宝,更新两珠宝之间的距离
dd[cur][istr[x][y]]=tmp.dis;
for(int i=0;i<4;i++) //能走
{
int xx=x+dir[i][0],yy=y+dir[i][1];
if(!iscan(xx,yy)||vis[xx][yy])
continue;
if(sa[xx][yy]==-1)
continue;
vis[xx][yy]=true;
int temp=xx*m+yy;
tmpdis[temp]=min(tmpdis[temp],tmp.dis+sa[xx][yy]);
myq.push(Node(temp,tmpdis[temp])); }
}
}
int main()
{
int t,a,b; scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
scanf("%d",&sa[i][j]);
scanf("%d",&k);
memset(istr,-1,sizeof(istr));
for(int i=0;i<k;i++)
{
scanf("%d%d",&a,&b);
istr[a][b]=i;
hash[i]=a*m+b; //将坐标从二维转化成一维便于处理
}
memset(dd,INF,sizeof(dd));
for(int i=0;i<k;i++) //求出每一个宝藏到其他宝藏的距离
{
cost[i]=INF;
dd[i][i]=0; //宝藏从自己到自己距离为0
dij(hash[i],i); //找到从i到所有的宝藏的最短距离
//printf("i:%d cost:%d\n",i,cost[i]);
}
memset(dp,INF,sizeof(dp));
for(int i=0;i<k;i++)
{ //dp[i][1<<i]是包括i本身花费的,+进来花费cost[i]
dp[i][1<<i]=cost[i]+sa[hash[i]/m][hash[i]%m];
// printf("i:%d dp[i][1<<i]:%d\n",i,dp[i][1<<i]);
}
int lim=1<<k;
for(int i=0;i<lim;i++)
{
for(int j=0;j<k;j++)
{
if(!(i&(1<<j))) //如果没有经过第j个珠宝
continue;
if(dp[j][i]==INF) //此状态无效
continue;
for(int p=0;p<k;p++)
{
if(i&(1<<p)) //p没有经过
continue;
if(dd[j][p]==INF)
continue; //最后经过的变成了p 依据j->p 更新后面的状态
dp[p][i|(1<<p)]=min(dp[p][i|(1<<p)],dp[j][i]+dd[j][p]);
}//dp[j][i]是已经求得的状态了
}
}
int ans=INF;
for(int i=0;i<k;i++)
{
// printf("%d %d\n",i,dp[i][lim-1]);
ans=min(ans,dp[i][lim-1]+cost[i]); //从最短路走出去
} printf("%d\n",ans); } return 0;
}
最短路+状态压缩dp(旅行商问题)hdu-4568-Hunter的更多相关文章
- Light OJ 1316 A Wedding Party 最短路+状态压缩DP
题目来源:Light OJ 1316 1316 - A Wedding Party 题意:和HDU 4284 差点儿相同 有一些商店 从起点到终点在走过尽量多商店的情况下求最短路 思路:首先预处理每两 ...
- 【状态压缩DP】HDU 4352 XHXJ'S LIS
题目大意 Vjudge链接 定义一个数的内部LIS长度表示这个数每个数位构成的序列的LIS长度,给出区间\([l,r]\),求区间内内部LIS长度为\(k\)的数的个数. 输入格式 第一行给出数据组数 ...
- HDU 4511 (AC自动机+状态压缩DP)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4511 题目大意:从1走到N,中间可以选择性经过某些点,比如1->N,或1->2-> ...
- HDU 3681 Prison Break(状态压缩dp + BFS)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3681 前些天花时间看到的题目,但写出不来,弱弱的放弃了.没想到现在学弟居然写出这种代码来,大吃一惊附加 ...
- hdu 4568 Hunter 最短路+dp
Hunter Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- HDU 1074 (状态压缩DP)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1074 题目大意:有N个作业(N<=15),每个作业需耗时,有一个截止期限.超期多少天就要扣多少 ...
- hdu 5025 Saving Tang Monk 状态压缩dp+广搜
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4092939.html 题目链接:hdu 5025 Saving Tang Monk 状态压缩 ...
- hdu 5094 Maze 状态压缩dp+广搜
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4092176.html 题目链接:hdu 5094 Maze 状态压缩dp+广搜 使用广度优先 ...
- hdu 4057 AC自己主动机+状态压缩dp
http://acm.hdu.edu.cn/showproblem.php?pid=4057 Problem Description Dr. X is a biologist, who likes r ...
随机推荐
- GPFS 安装测试
简介 GPFS(General Parallel File System ,GPFS) 是 IBM 公司第一个共享文件系统,起源于 IBM SP 系统上使用的虚拟共享磁盘技术( VSD ).作为这项技 ...
- HDU 1213(并查集)
How Many Tables Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)T ...
- HDU2874【倍增、ST】
题目链接[https://vjudge.net/problem/HDU-2874] 题意: 输入一个森林,总节点不超过N(N<10000),由C次询问(C<1000000),每次询问两个点 ...
- 埃及分数 a* 搜索 知识点mark
题意 在古埃及,人们使用单位分数的和(即1/a,a是自然数)表示一切有理 数. 例如,2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为在加数中不允许有相同的. 对于一个分数a/b,表示方法 ...
- PHP配置文件经典漏洞
phithon师父在小蜜圈里放了一个经典的配置文件写入问题漏洞. <?phpif(!isset($_GET['option'])) die();$str = addslashes($_GET[' ...
- MAMP PRO 下安装 memcache
本人PHP用的是 5.5.10,编译 memcache 模块需要用到 php 源码,mamp 不自带,到 php 官网下一个 php-5.5.11.tar.gz, 解压后,生成 zend_config ...
- eclipse.ini 文件使用说明
http://wiki.eclipse.org/Eclipse.ini Overview Eclipse startup is controlled by the options in $ECLIPS ...
- CC1101是一种低成本真正单片的UHF收发器
CC1101是一种低成本真正单片的UHF收发器,为低功耗无线应用而设计.电路主要设定为在315.433.868和915MHz的ISM(工业,科学和医学)和SRD(短距离设备)频率波段,也可以容易地设置 ...
- gdb参考手册
http://www.sourceware.org/gdb/current/onlinedocs/gdb.html
- 源码管理--llorch的Visual Studio基本教程(四)
通用的演示样例说明: 本系列博客仅仅讨论工具的基础,不讨论不论什么语言. 甚至不讨论快捷键:-) 能够用鼠标就完毕本教程 IDE默认指代的是Visual Studio 2013 Community E ...