• Connect(bzoj 1948)


    Description

    给定一个R*C大小的迷宫,其中R,C均为奇数 迷宫中坐标为两个奇数的点不能通过,称为障碍,迷宫中其他不能通过的点统称为墙壁 坐标为两个偶数的点可以通过,称为房间,迷宫中其他可通过的点称为走廊。迷宫有边界 迷宫中放置有若干个物品(偶数个),物品一定放置在房间中 问如何将这些物品配对可以使得所有物品对之间路径的总和最小,任两条路径不能相交,并求路径

    Input

    第一行输入为两个整数: R与C(5 ≤ R ≤ 25,5 ≤ C ≤ 80) 其中R为行数,C为列数,R,C均为奇数。 接下来的R行每行包括C个字符,每个字符都是’+’、’|’、’-‘、空格或’X’中的一个,分别表示障碍及两种墙壁、空格表示房间或可通过的走廊,X表示房间中的物品。

    Output

    输出的第一行是一个整数,即最小分值。
    /*
        插头DP 
        这道题看了一晚上了,还是有很多地方不理解,Orz~ 
    */
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    using namespace std;
    int n,m,inf,cnt;
    int f[2][26][(1<<13)+10],blo[110][31][4];
    char s1[31][110],s[110][31];
    int dx[4]={0,-1,0,1};
    int dy[4]={-1,0,1,0};
    void upd(int &x,int y){x=min(x,y);}
    int trs(int x,int y){
        x=(x>>2)<<1;x|=y&1;
        x|=((y&2)>>1)<<m;
        return x;
    }
    int main(){
        scanf("%d%d",&n,&m);gets(s1[0]+1);
        for(int i=1;i<=n;i++) gets(s1[i]+1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                s[j][i]=s1[i][j],cnt+=(s1[i][j]=='X');
        swap(n,m);
        for(int i=2;i<n;i+=2)
            for(int j=2;j<m;j+=2)
                for(int k=0;k<4;k++)
                    blo[i>>1][j>>1][k]=(s[i+dy[k]][j+dx[k]]!=' ');
        n/=2;m/=2;
        memset(f[1],0x3f,sizeof(f[1]));
        inf=f[1][1][0];f[1][1][0]=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                if(j==m)
                    memset(f[~i&1],0x3f,sizeof(f[~i&1]));
                for(int k=0;k<1<<m+1;k++){
                    if(f[i&1][j][k]==inf) continue;
                    int *nex;
                    if(j==m) nex=f[~i&1][1];
                    else nex=f[i&1][j+1];
                    int v1=blo[i][j][2],v2=blo[i][j][3],val=f[i&1][j][k];
                    if(s[i<<1][j<<1]=='X'){
                        if((k&3)==3) continue;
                        if((k&3)==0){
                            if(!v2) upd(nex[trs(k,1)],val+1);
                            if(!v1) upd(nex[trs(k,2)],val+1);
                        }
                        else upd(nex[trs(k,0)],val);
                    }
                    else{
                        if((k&3)==3) upd(nex[trs(k,0)],val+1);
                        else if((k&3)==0){
                            upd(nex[trs(k,0)],val);
                            if(!v1&&!v2) upd(nex[trs(k,3)],val+3);
                        }
                        else {
                            if(!v2) upd(nex[trs(k,1)],val+2);
                            if(!v1) upd(nex[trs(k,2)],val+2);
                        }
                    }
                }
            }
        printf("%d
    ",f[(n+1)&1][1][0]+cnt/2);
        return 0;
    }
  • 相关阅读:
    Java 多线程系列02
    Java 多线程系列01
    java io流03 字符流
    java JDBC系列
    java io流02 字节流
    Helidon使用心得
    camel 解析
    Spring 源码分析
    java代码实现分页功能
    SpringBoot Tomcat启动报错
  • 原文地址:https://www.cnblogs.com/harden/p/6561909.html
Copyright © 2020-2023  润新知