题目链接:

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的更多相关文章

  1. Light OJ 1316 A Wedding Party 最短路+状态压缩DP

    题目来源:Light OJ 1316 1316 - A Wedding Party 题意:和HDU 4284 差点儿相同 有一些商店 从起点到终点在走过尽量多商店的情况下求最短路 思路:首先预处理每两 ...

  2. 【状态压缩DP】HDU 4352 XHXJ'S LIS

    题目大意 Vjudge链接 定义一个数的内部LIS长度表示这个数每个数位构成的序列的LIS长度,给出区间\([l,r]\),求区间内内部LIS长度为\(k\)的数的个数. 输入格式 第一行给出数据组数 ...

  3. HDU 4511 (AC自动机+状态压缩DP)

    题目链接:  http://acm.hdu.edu.cn/showproblem.php?pid=4511 题目大意:从1走到N,中间可以选择性经过某些点,比如1->N,或1->2-> ...

  4. HDU 3681 Prison Break(状态压缩dp + BFS)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3681 前些天花时间看到的题目,但写出不来,弱弱的放弃了.没想到现在学弟居然写出这种代码来,大吃一惊附加 ...

  5. hdu 4568 Hunter 最短路+dp

    Hunter Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  6. HDU 1074 (状态压缩DP)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1074 题目大意:有N个作业(N<=15),每个作业需耗时,有一个截止期限.超期多少天就要扣多少 ...

  7. hdu 5025 Saving Tang Monk 状态压缩dp+广搜

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4092939.html 题目链接:hdu 5025 Saving Tang Monk 状态压缩 ...

  8. hdu 5094 Maze 状态压缩dp+广搜

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4092176.html 题目链接:hdu 5094 Maze 状态压缩dp+广搜 使用广度优先 ...

  9. hdu 4057 AC自己主动机+状态压缩dp

    http://acm.hdu.edu.cn/showproblem.php?pid=4057 Problem Description Dr. X is a biologist, who likes r ...

随机推荐

  1. prim 算法和 kruskal算法

    Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...

  2. 在eclipse中安装TestNG

    https://www.cnblogs.com/baixiaozheng/p/4989856.html 1.可借助Eclipse的Marketplace来安装TestNG Eclipse插件 a.打开 ...

  3. django配置templates、static、media和连接mysql数据库

    1.模板文件 # =======templates配置======= if os.path.exists(os.path.join(BASE_DIR, 'templates')) is False: ...

  4. 使用matplotlib绘图(四)之散点图

    # 使用matplotlib绘制散点图 import numpy as np import matplotlib.pyplot as plt # 设置全局刻度标签大小 plt.rcParams['xt ...

  5. WebLogic Server

    前几天,看了几集J2ee , 给我的感觉就是,看不懂!! 一点也不懂! 那怎么办呢? 听老师的,不管懂不懂,先看看再说.接下来,就开始了J2ee "艰苦"的历程.在J2ee中,经常 ...

  6. [BZOJ5093]图的价值(NTT+第二类Stirling数)

    5093: [Lydsy1711月赛]图的价值 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 250  Solved: 130[Submit][Sta ...

  7. 【并查集】BZOJ1370- [Baltic2003]Gang团伙

    [题目大意] 在某城市里住着n个人,任何两个认识的人不是朋友就是敌人,而且满足: 1. 我朋友的朋友是我的朋友: 2. 我敌人的敌人是我的朋友: 所有是朋友的人组成一个团伙.告诉你关于这n个人的m条信 ...

  8. [转]Android Studio开发入门-引用jar及so文件

    注意: 1.jar包在app的libs目录 2.so文件放在src/main”目录中名为“jniLibs”的目录 一.引用jar文件    1.将jar文件复制.粘贴到app的libs目录中:    ...

  9. NSDictionary , NSMutableDictionary, NSMutableDictionary 和 NSMutableSet)相当于java的map、set

    1 NSDictionary 和 NSMutableDictionary NSDictionary  :就是java中的map; 放入对象是键值对 key-value  , 同样 秉持了一样的原则,只 ...

  10. 腾讯PHP工程师面试题两份

    试题一: PHP开发工程师笔试试卷 姓名:__________ 一.PHP开发部分 1.合并两个数组有几种方式,试比较它们的异同 2.请写一个函数来检查用户提交的数据是否为整数(不区分数据类型,可以为 ...