最短路+状态压缩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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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_queuemyq;
   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;ip 更新后面的状态
               dp[p][i|(1<


你可能感兴趣的:(动态规划,最短路,动态规划)