HDU 4568 Hunter (状态压缩)

举报
Linux猿 发表于 2021/08/05 00:21:17 2021/08/05
【摘要】 题目链接~~> 做题感悟:这题做了好几个小时,但是这题A的还算顺利没有什么坑。 解题思路:BFS + 优先队列+状态压缩      (1)先用BFS+优先队列处理出各点到其他点和边界的最短路径。      (2)用状态压缩枚举每种情况就ok了。 代码: #include<stdio.h&gt...

题目链接~~>

做题感悟:这题做了好几个小时,但是这题A的还算顺利没有什么坑。

解题思路:BFS + 优先队列+状态压缩

     (1)先用BFS+优先队列处理出各点到其他点和边界的最短路径。

     (2)用状态压缩枚举每种情况就ok了。

代码:


  
  1. #include<stdio.h>
  2. #include<iomanip>
  3. #include<vector>
  4. #include<queue>
  5. #include<fstream>
  6. #include<string.h>
  7. #include<stdlib.h>
  8. #include<string.h>
  9. #include<algorithm>
  10. #include<iostream>
  11. #define INT long long int
  12. using namespace std ;
  13. const int INF = 999999999 ;
  14. const int MX = 200 + 10 ;
  15. const int MY = 15 ;
  16. int n,m,num ;
  17. bool vis[MX][MX] ;
  18. int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1} ;
  19. int a[MX],dg[MX],g[MX][MX],flag[MX][MX],d[MX][MX],dp[1<<14][14] ;
  20. struct node
  21. {
  22. int x,y,step ;
  23. friend bool operator <(const node &a,const node &b)
  24. {
  25. return a.step > b.step ;
  26. }
  27. } ;
  28. bool judge(int x,int y)
  29. {
  30. if(x<0||y<0||x>=n||y>=m||vis[x][y]||g[x][y]==-1)
  31. return false ;
  32. return true ;
  33. }
  34. int bfs(int x,int y)// BFS+优先队列求最短路
  35. {
  36. int best=INF ;
  37. memset(vis,false,sizeof(vis)) ;
  38. priority_queue<node>q ;
  39. node curt,next ;
  40. curt.x=x ;
  41. curt.y=y ;
  42. curt.step=0 ;
  43. vis[x][y]=true ;
  44. q.push(curt) ;
  45. while(!q.empty())
  46. {
  47. curt=q.top() ;
  48. q.pop() ;
  49. if(flag[curt.x][curt.y]!=-1) // 此怪物与彼怪物的距离
  50. {
  51. int u = flag[x][y] ;
  52. int v=flag[curt.x][curt.y] ;
  53. d[u][v]=curt.step ;
  54. }
  55. if(!curt.x||!curt.y||curt.x==n-1||curt.y==m-1) // 求当前怪物点距离边界的最短距离
  56. best=min(best,curt.step) ;
  57. for(int i=0 ;i<4 ;i++)
  58. {
  59. next.x=curt.x+dx[i] ;
  60. next.y=curt.y+dy[i] ;
  61. if(judge(next.x,next.y))
  62. {
  63. next.step=curt.step+g[next.x][next.y] ;
  64. vis[next.x][next.y]=true ;
  65. q.push(next) ;
  66. }
  67. }
  68. }
  69. return best ;
  70. }
  71. void DP_SC() // 状态压缩
  72. {
  73. for(int S=0 ;S<(1<<num) ;S++)
  74. for(int i=0 ;i<num ;i++)
  75. if(dp[S][i]!=-1)
  76. {
  77. for(int j=0 ;j<num ;j++)
  78. if(!(S&(1<<j))&&i!=j&&d[i][j]!=-1)
  79. {
  80. if(dp[S|(1<<j)][j]==-1)
  81. dp[S|(1<<j)][j]=dp[S][i]+d[i][j] ;
  82. else
  83. dp[S|(1<<j)][j]=min(dp[S|(1<<j)][j],dp[S][i]+d[i][j]) ;
  84. }
  85. }
  86. int ans = INF ;
  87. for(int i=0 ;i<num ;i++)
  88. if(dp[(1<<num)-1][i]!=-1&&dg[i]!=-1)
  89. {
  90. int x=a[i]/m,y=a[i]%m ;
  91. ans = min(ans,dp[(1<<num)-1][i]+dg[i]-g[x][y]) ;
  92. }
  93. cout<<( ans!=INF ? ans : 0)<<endl ;
  94. }
  95. int main()
  96. {
  97. int Tx,x,y ;
  98. scanf("%d",&Tx) ;
  99. while(Tx--)
  100. {
  101. memset(dp,-1,sizeof(dp)) ;
  102. memset(d,-1,sizeof(d)) ; // 如果两点无法达到为 -1
  103. memset(dg,-1,sizeof(dg)) ; // 如果某点无法到达边界为 -1
  104. memset(flag,-1,sizeof(flag)) ; // 如果某点没有怪物为 -1
  105. scanf("%d%d",&n,&m) ;
  106. for(int i=0 ;i<n ;i++)
  107. for(int j=0 ;j<m ;j++)
  108. scanf("%d",&g[i][j]) ;
  109. bool fx=false ;
  110. scanf("%d",&num) ;
  111. for(int i=0 ;i<num ;i++)
  112. {
  113. scanf("%d%d",&x,&y) ;
  114. a[i]=x*m+y ;
  115. if(g[x][y]==-1) fx=true ;
  116. flag[x][y]=i ;// 标记此点有怪物
  117. }
  118. if(fx)// 如果某个点无法到达
  119. {
  120. cout<<0<<endl ;
  121. continue ;
  122. }
  123. for(int i=0 ;i<num ;i++) // 求每个怪物的间距
  124. {
  125. x=a[i]/m ; y =a[i]%m ;
  126. dg[i]=bfs(x,y)+g[x][y] ; // 距离最近的边界的距离
  127. int u = flag[x][y] ;
  128. d[u][u]=0 ;
  129. dp[1<<i][i]=dg[i] ;
  130. }
  131. DP_SC() ;
  132. }
  133. return 0 ;
  134. }


文章来源: blog.csdn.net,作者:Linux猿,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/nyist_zxp/article/details/38046525

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。