UVALive - 6455-枚举&BFS-Stealing Harry Potter's Precious

https://vjudge.net/problem/UVALive-6455
给定一个初始点,问你经过k个点,所用路径最短。
如果不能都经过(有墙有分割),那么就输出-1
思路:广搜查找最短的,后来又发现如果单单从初始点广搜,得到的不一定是最优的方案。所以枚举每个k点作为初始点,然后取最小值。

#include <bits/stdc++.h>
using namespace std;
int fx[2][4]{{1,-1,0,0},{0,0,1,-1}};
const int maxn=105;
struct Node{
       int x,y;
       int num;//步数
       Node(){};
       Node(int _a,int _b,int _c){
           x=_a;y=_b;num=_c;
       };
};
int x;
int y;
char a[maxn][maxn];
bool vis[maxn][maxn];
int m,n;
int k;
int  solve(int x1,int y1){
    //cout<<"************************"<<endl;
    char b[maxn][maxn];
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++)
            b[i][j]=a[i][j];
    }
    queue<Node>q;
    q.push(Node(x,y,0));
    memset(vis,false,sizeof(vis));
    vis[x1][y1]=true;
    //cout<<x<<"!!!"<<y<<endl;
    int ans=0;
    int tim=0;
    while(!q.empty()){
         Node u=q.front();
         q.pop();
         for(int i=0;i<4;i++){
             int x2=u.x+fx[0][i];
             int y2=u.y+fx[1][i];
             if(x2<=0||x2>m||y2<=0||y2>n) continue;
             if(vis[x2][y2]) continue;
             vis[x2][y2]=true;
             if(b[x2][y2]=='*'){
                b[x2][y2]='.';
                while(!q.empty()) q.pop();
                memset(vis,false,sizeof(vis));
                ans+=u.num+1;
                tim++;
                q.push(Node(x2,y2,0));
                break;
                //cout<<q.size()<<"daxiao"<<endl;
             }
             else if(b[x2][y2]=='.'){
                  //cout<<"!!"<<endl;
                  q.push(Node(x2,y2,u.num+1));
             }
         }
    }
    if(tim!=k)
        return -1;
    else
      return ans;
}
int main(){
    while(~scanf("%d%d",&m,&n)){
          if(m==0&&n==0)break;
          getchar();
          for(int i=1;i<=m;i++){
              for(int j=1;j<=n;j++){
                scanf("%c",&a[i][j]);
                //cout<<a[i][j]<<endl;
               if(a[i][j]=='@')
               {  x=i;
                  y=j;
               }
               }
               getchar();
          }
          memset(vis,false,sizeof(vis));
          //cout<<"!!"<<endl;
          scanf("%d",&k);
          //cout<<k<<endl;
          int a1[5],b1[5];
          //for(int i=0;i<4;i++)
            //cout<<i<<"!!"<<fx[1][i]<<" "<<fx[0][i]<<endl;
          for(int i=0;i<k;i++){
              scanf("%d%d",&a1[i],&b1[i]);
              //cout<<a1<<" ."<<b1<<endl;
              a[a1[i]][b1[i]]='*';
          }
          int min1=-1;
          min1=solve(x,y);
         for(int i=0;i<k;i++){
         int ans=solve(a1[i],b1[i]);
            if(ans==-1) {
                    //cout<<a1[i]<<"!!"<<b1[i]<<endl;
                    min1=-1;break;}
            else
                min1=min(min1,ans);
         }
         printf("%d\n",min1);


    }


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值