HDU-5025 2014广州网络赛 Saving Tang Monk 状压+BFS

给出一个N*N的矩阵,开启牢门需要收集齐m种钥匙,且必须收集了前i-1种钥匙才能收集第i种钥匙,最终收集齐了回到关押唐僧的房间拯救唐僧,经过一个'S'的房间时需要额外耗时把蛇打死,蛇最多5条,所以状压一下用优先队列BFS求最小时间即可。

  1. #include <iostream>  
  2. #include <cstdio>  
  3. #include <cmath>  
  4. #include <queue>  
  5. #include <vector>  
  6. #include <cstring>  
  7. #include <algorithm>  
  8. #define inf 1<<29  
  9. using namespace std;  
  10. const int maxn=111;  
  11. char str[maxn][maxn];  
  12. int n,m;  
  13. int ans;  
  14. int map[maxn][maxn];  
  15. int dp[maxn][maxn][11];//访问到坐标(x,y)身上有i个钥匙的步数   
  16. int dir[4][2]= {0,1,0,-1,1,0,-1,0};  
  17. struct node  
  18. {  
  19.     int x,y;  
  20.     int step;  
  21.     int snake;  
  22.     int k;  
  23.     friend bool operator<(node a,node b)  
  24.     {  
  25.         return a.step>b.step;  
  26.     }  
  27. };  
  28. int go(int x,int y)  
  29. {  
  30.     if(x>=0&&x<n&&y>=0&&y<n&&str[x][y]!='#')  
  31.     {  
  32.         return 1;  
  33.     }  
  34.     return 0;  
  35. }  
  36. void solve(int x,int y)  
  37. {  
  38.     priority_queue<node> q;  
  39.     node front,now;  
  40.     now.x=x;  
  41.     now.y=y;  
  42.     now.step=0;  
  43.     now.snake=0;  
  44.     now.k=0;  
  45.     q.push(now);  
  46.     while(!q.empty())  
  47.     {  
  48.         front=q.top();  
  49.         q.pop();  
  50.         x=front.x;  
  51.         y=front.y;  
  52.         if(str[x][y]=='T'&&front.k==m)  
  53.         {  
  54.             ans=min(ans,front.step);  
  55.         }  
  56.         for(int i=0;i<4;i++)  
  57.         {  
  58.             int fx=x+dir[i][0];  
  59.             int fy=y+dir[i][1];  
  60.             now.x=fx;  
  61.             now.y=fy;  
  62.             now.step=front.step+1;  
  63.             now.snake=front.snake;  
  64.             now.k=front.k;  
  65.             if(go(fx,fy))  
  66.             {  
  67.                 if(str[fx][fy]=='S')  
  68.                 {  
  69.                     int k=map[fx][fy];  
  70.                     if(((1<<k)&now.snake)==0)  
  71.                     {  
  72.                         now.step++;  
  73.                         now.snake|=(1<<k);  
  74.                     }  
  75.                 }  
  76.                 if(str[fx][fy]-'0'==now.k+1)  
  77.                 {  
  78.                     now.k+=1;  
  79.                 }  
  80.                 if(dp[fx][fy][now.k]>now.step&&now.step<ans)  
  81.                 {  
  82.                     dp[fx][fy][now.k]=now.step;  
  83.                     q.push(now);  
  84.                 }  
  85.             }   
  86.         }  
  87.     }  
  88. }  
  89. int main()  
  90. {  
  91.     int cnt;  
  92.     while(scanf("%d%d",&n,&m)!=EOF)  
  93.     {  
  94.         if(n==0&&m==0)  
  95.         {  
  96.             break;  
  97.         }  
  98.         cnt=0;  
  99.         for(int i=0;i<n;i++)  
  100.         {  
  101.             scanf("%s",str[i]);  
  102.         }  
  103.         for(int i=0;i<n;i++)  
  104.         {  
  105.             for(int j=0;j<n;j++)  
  106.             {  
  107.                 if(str[i][j]=='S')  
  108.                 {  
  109.                     map[i][j]=cnt++;  
  110.                 }  
  111.                 for(int k=0;k<11;k++)  
  112.                 {  
  113.                     dp[i][j][k]=inf;  
  114.                 }  
  115.             }  
  116.         }  
  117.         ans=inf;  
  118.         for(int i=0;i<n;i++)  
  119.         {  
  120.             for(int j=0;j<n;j++)  
  121.             {  
  122.                 if(str[i][j]=='K')  
  123.                 {  
  124.                     solve(i,j);  
  125.                     break;  
  126.                 }  
  127.             }  
  128.         }  
  129.         if(ans==inf)  
  130.         {  
  131.             printf("impossible\n");  
  132.         }  
  133.         else  
  134.         {  
  135.             printf("%d\n",ans);  
  136.         }  
  137.     }  
  138.     return 0;  


万州人才网www.wzrjob.com友情转载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值