• QDUOJ 来自xjy的签到题(bfs+状压dp)


    来自xjy的签到题
     

    Description

     

    爱丽丝冒险来到了红皇后一个n*n大小的花园,每个格子由'.'或'#'表示,'.'表示爱丽丝可以到达这个格子,‘#’表示爱丽丝不能到达这个格子,爱丽丝每1分钟可以移动到非'#'的相邻格子(与当前所在格子具有公共边)。花园下面有m个隧道,每个隧道有一个出口和一个入口。当爱丽丝到达隧道的入口时,她可以选择(也可以不选择)进入隧道入口,并通过隧道一次,然后立即(不花费时间)出现在隧道出口。爱丽丝一开始可以降临在花园的任何地方。有好奇心的爱丽丝想知道,她通过所有隧道且每个隧道仅通过一次最少需要花费多少时间。(注意,爱丽丝不能从隧道出口通往隧道入口)

    Input

     

    输入包含多个测试用例,不超过10组。对于每个测试用例,第一行输入n(1<=n<=15)和m(1<=m<=15),分别表示地图的大小为n*n和m个隧道。然后给出一个n行n列的花园地图,由'.'或'#'组成,'.'表示爱丽丝可以到达这个格子,‘#’表示爱丽丝不能到达这个格子。接下来m行,表示m个隧道。每行四个正整数x1,y1,x2,y2(1<=x1,x2,y1,y2<=15),表示隧道的入口为(x1,y1),出口为(x2,y2)。数据保证隧道入口和出口位置不会出现在‘#’上。

    Output

     

    对于每个测试用例,你需要输出一个整数,表示爱丽丝通过所有隧道仅一次的最少时间。如果爱丽丝无法通过所有隧道,则输出-1。

    Sample Input 1 

    5 4
    ....#
    ...#.
    .....
    .....
    .....
    2 3 1 4
    1 2 3 5
    2 3 3 1
    5 4 2 1

    Sample Output 1

    7

    Hint

    对于样例,爱丽丝可以一开始降临在(2,3)并穿过第一个隧道到达(1,4),然后花费2分钟走向(1,2)并穿过第二个隧道到达(3,5),然后花费3分钟走向(5,4)并穿过第四个隧道到达(2,1),最后花费2分钟走向(2,3)并穿过第三个隧道到达(3,1)。至此通过所有隧道,并花费7分钟时间。

    注意本题时间限制和空间限制

    将隧道视为点,先bfs预处理出两两隧道间的距离,然后使用状压dp求出最小时间。

    转移方程:dp[目标状态][目标点]=min(dp[目标状态][目标点],dp[当前状态][当前点]+dis[当前点][目标点])。

    #include<bits/stdc++.h>
    #define MAX 16
    #define INF 0x3f3f3f3f
    using namespace std;
    
    char s[MAX][MAX];
    int b[MAX][MAX],dis[MAX][MAX];
    int dp[1<<15][MAX];
    int t[4][2]={1,0,0,1,-1,0,0,-1};
    struct Node{
        int bx,by,ex,ey;
    }a[MAX];
    struct Node2{
        int x,y,s;
    }node;
    queue<Node2> q;
    
    int bfs(Node u,Node v,int n){
        memset(b,0,sizeof(b));
        while(q.size()){
            q.pop();
        }
        if(u.ex==v.bx&&u.ey==v.by) return 0;
        node.x=u.ex;
        node.y=u.ey;
        node.s=0;
        q.push(node);
        b[node.x][node.y]=1;
        while(q.size()){
            for(int i=0;i<4;i++){
                Node2 now=q.front();
                int tx=now.x+t[i][0];
                int ty=now.y+t[i][1];
                if(tx<1||tx>n||ty<1||ty>n) continue;
                if(s[tx][ty]=='#'||b[tx][ty]==1) continue;
                b[tx][ty]=1;
                if(tx==v.bx&&ty==v.by){
                    return now.s+1;
                }
                node.x=tx;
                node.y=ty;
                node.s=now.s+1;
                q.push(node);
            }
            q.pop();
        }
        return INF;
    }
    int main()
    {
        int n,m,i,j,k;
        while(~scanf("%d%d",&n,&m)){
            for(i=1;i<=n;i++){
                scanf(" %s",s[i]+1);
            }
            for(i=1;i<=m;i++){
                scanf("%d%d%d%d",&a[i].bx,&a[i].by,&a[i].ex,&a[i].ey);
            }
            memset(dis,INF,sizeof(dis));
            for(i=1;i<=m;i++){
                for(j=1;j<=m;j++){
                    if(i==j) continue;
                    dis[i][j]=bfs(a[i],a[j],n);
                }
            }
            memset(dp,INF,sizeof(dp));
            for(i=1;i<=m;i++){
                dp[1<<(i-1)][i]=0;
            }
            for(i=0;i<(1<<m);i++){
                for(j=1;j<=m;j++){
                    if(!(i&(1<<(j-1)))) continue;
                    for(k=1;k<=m;k++){
                        if(j==k||dis[j][k]==INF||!(i&(1<<(k-1)))) continue;
                        dp[i][k]=min(dp[i][k],dp[i^(1<<(k-1))][j]+dis[j][k]);
                    }
                }
            }
            int ans=INF;
            for(i=1;i<=m;i++){
                ans=min(ans,dp[(1<<m)-1][i]);
            }
            if(ans==INF) printf("-1
    ");
            else printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Vue 2.x windows环境下安装
    VSCODE官网下载缓慢或下载失败 解决办法
    angular cli 降级
    Win10 VS2019 设置 以管理员身份运行
    XSHELL 连接 阿里云ECS实例
    Chrome浏览器跨域设置
    DBeaver 执行 mysql 多条语句报错
    DBeaver 连接MySql 8.0 报错 Public Key Retrieval is not allowed
    DBeaver 连接MySql 8.0报错 Unable to load authentication plugin 'caching_sha2_password'
    Linux系统分区
  • 原文地址:https://www.cnblogs.com/yzm10/p/9568363.html
Copyright © 2020-2023  润新知