最短路+状态压缩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 ...
随机推荐
- 51nod 1962区间计数(单调栈加二分)
题目要求是求出两个序列中处于相同位置区间并且最大值相同的区间个数,我们最直观的感受就是求出每个区间的最大值,这个可以O(N)的求,利用单调栈求出每个数作为最大值能够覆盖的区间. 然后我们可以在进行单调 ...
- BZOJ 4516: [Sdoi2016]生成魔咒 后缀自动机 性质
http://www.lydsy.com/JudgeOnline/problem.php?id=4516 http://blog.csdn.net/doyouseeman/article/detail ...
- Spring Mvc 前台数据的获取、SpringMvc 表单数据的获取
首先在web.xml 里面配置一个编码过滤器 <!-- springmvc框架本身没有处理请求编码,我们自己配置一个请求编码过滤器 --> <filter> <filte ...
- 通过wifi上网,桥接模式下virtualBox虚拟机无法连上网的解决办法
https://jingyan.baidu.com/article/948f59242e601dd80ff5f929.html
- python开发_gzip_压缩|解压缩gz文件_完整版_博主推荐
''' gzip -- 支持gzip文件 源文件:Lib/gzip.py 这个模块提供了一些简单的接口来对文件进行压缩和解压缩,类似于GNU项目的gzip和gunzip. 数据的压缩源于zlib模块的 ...
- HDU 5301 Buildings 数学
Buildings 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5301 Description Your current task is to m ...
- Octopress + GitHub Page 搭建个人博客
Tips:博客已搬家,新地址:http://wanxudong.top 首先说明两个关键术语: Octopress Octopress是基于 Jekyll 的博客框架.他们的关系就像 jQuery 与 ...
- 【原】【Git】EGit强制覆盖本地文件
今天带来的是EGit使用中有时会用到的一个技巧,强制覆盖本地.EGit强制覆盖远端(其实没有这个说法),在另一篇文章中写了http://www.cnblogs.com/guodongdidi/p/48 ...
- Ubuntu 16.09下iptables通过raw表实现日志输出和调试
1.先配置好raw表日志打点功能 参考:http://www.cnblogs.com/EasonJim/p/8413563.html 2.配置好messages文件 参考:http://www.cnb ...
- 用C++/CLI搭建C++和C#之间的桥梁(三)—— 基本类型
数值类型 对于基本的数值类型,在C++/CLI中是可以直接映射为托管类型的数值的,可以同时应用于托管类型和非托管类型,编译器会将其自动转换. 基本类型 System命名空间中对应的类 注释/用法 bo ...