题目链接:

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. Linux安装apache服务

    1.通过yum包下载安装httpd yum -y install httpd*(等待安装) 到下面就安装完毕 2.启动apache服务 service httpd restart 3.现在就可以查看a ...

  2. [JSOI2007]文本生成器 --- AC自动机 + DP

    [JSOI2007]文本生成器 题目描述: JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版. 该软件可以随机 ...

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

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

  4. Unity随手机

    该文章持续更新! 协程的返回值必需是 IEnumerator 协程的参数不能加关键字 ref 或 out 在函数 Update 和 FixedUpdate 中不能使用 yield 语句,但可以启动协程 ...

  5. BZOJ 4027: [HEOI2015]兔子与樱花 树上dp

    4027: [HEOI2015]兔子与樱花 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline ...

  6. C语言 关键字

    auto 局部变量(自动储存)break无条件退出程序最内层循环case switch语句中选择项char单字节整型数据const定义不可更改的常量值continue中断本次循环,并转向下一次循环de ...

  7. 复制到剪切板js代码(转)

    <script type="text/javascript" language="javascript"> //复制到剪切板js代码 functio ...

  8. Java常量定义需要注意的两点

    在任何开发语言中,都需要定义常量.在Java开发语言平台中也不例外.不过在Java常量定义的时候,跟其他语言有所不同.其有自己的特色.在这篇文章中,主要针对Java语言中定义常量的注意事项进行解析,帮 ...

  9. 1036: [ZJOI2008]树的统计Count (树链剖分)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3401  Solved: 1418[Submit] ...

  10. ELM327 蓝牙/WIFI/USB diagnostic interface