• CEOI2014 wall Spoiler


    不知不觉又好久没有写博客了。不能这样一直放着。在适当的时候总结一下,回首过去走过的,总会有一些感触和经验,写题解也是为了大体回忆一下自己的思路,让自己对这题掌握更深刻。暂停一下,是为了稳住前进的脚步,让将来的步伐迈得更加稳健。加油!

    好了。。废话到此打住,上题。

    Description

     

    Input

    Output

     

    Sample Input

    3 3
    1 0 0
    1 0 0
    0 0 1
    1 4 9 4
    1 6 6 6
    1 2 2 9
    1 1 1
    4 4 4
    2 4 2
    6 6 6

    Sample Output

    38
     

    Data Constraint

     

    Hint

    样例解释:

    这题之前雅礼集训的时候做过类似的,30分的状压设f[x,y,s]表示走到(x,y)各个关键点的状态为s的最短路。考试的时候直接写了30的,结果还写挂10分滚粗了。。。

    正解》首先有个结论:最优解一定会把(起点到每个关键点的最短路径)包含在里面。

    反证》如果某条最短路没有被包含,那么它和环一定会有两个交点,那么这两个交点在环上的距离就大于它在最短路中的距离,则不是最优解。(如下图,黑色为走出的环,蓝色为最短路,那么红色那段一定大于蓝色那段,即黑环不是最优解。

    ok.现在有了这个结论,问题变成了,我们要从原点出发,绕一圈把那些最短路和特殊点都绕进来,所需要的最短路径是多少。

    标解使用了拆点的做法。把原图的每个点拆成四个。这样原图中的一条边在新图中就变成了一个长方形(圈起来的)

    因为要包含最短路径不能穿过它,所以我们把与原图中路径垂直的两条短边cut掉,平行的两条长边赋成原图的中的边权,就可以实现把最短路绕进去了。对于关键点,我们把它四周的边以及延伸出去的短边cut掉就可以了。最后跑一次从(1,2)到(2,1)的最短路,得到的即是Ans

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    
    using namespace std;
    typedef long long ll;
    
    ll d[811][811],fz;
    int vis[811][811],c[11][11];
    ll len[811][811][5],nl[811][811][5];
    int cy[401*401][2],que[401*401][2];
    int tc,n,m,i,j,k,x,y,nx,ny,tl;
    bool pe[402][402][5];
    
    struct dd{
        int x,y;
        ll dis;
        bool operator < (dd a) const
        {
            return dis>a.dis;
        };
    };
    
    priority_queue<dd> H;
    
    void dij(int sx,int sy)
    {
        dd st,now;
        int x,y,i,nx,ny;
        memset(d,127,sizeof(d));
        d[sx][sy]=0;
        tl++;
        st.x=sx;st.y=sy;st.dis=0;
        H.push(st);
        while(!H.empty()){
            now=H.top();
            H.pop();
            x=now.x;y=now.y;
            if(vis[x][y]==tl)continue;
            vis[x][y]=tl;
            for(i=1;i<=4;i++){
                nx=x+c[i][0];ny=y+c[i][1];
                if(nx<1||nx>n||ny<1||ny>m)continue;
                if(d[x][y]+len[x][y][i]<d[nx][ny]){
                    d[nx][ny]=d[x][y]+len[x][y][i];
                    st.x=nx;st.y=ny;st.dis=d[nx][ny];
                    H.push(st);
                }
            }
        }
    }
    
    void bfs(int sx,int sy)
    {
        int l,r,x,y,nx,ny,i;
        l=r=1;
        que[l][0]=sx;que[l][1]=sy;
        while(l<=r){
            x=que[l][0];y=que[l][1];
            for(i=1;i<=4;i++){
                nx=x+c[i][0];ny=y+c[i][1];
                if(nx<1||nx>n||ny<1||ny>m)continue;
                if(d[nx][ny]+len[x][y][i]==d[x][y]){
                    r++;
                    que[r][0]=nx;que[r][1]=ny;
                    pe[x][y][i]=false;
                    if(i<=2)pe[nx][ny][3-i]=false;
                    else pe[nx][ny][7-i]=false;
                }
            }
            l++;
        }
    }
    
    int main()
    {
        c[1][0]=0;c[1][1]=1;c[2][0]=0;c[2][1]=-1;c[3][0]=1;c[3][1]=0;c[4][0]=-1;c[4][1]=0;
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++){
                scanf("%d",&k);
                if(k==1){
                    tc++;
                    cy[tc][0]=i;cy[tc][1]=j;
                }
            }
        for(i=1;i<=n;i++)
            for(j=1;j<=m+1;j++){
                scanf("%d",&k);
                len[i][j][3]=k;
                len[i+1][j][4]=k;
            }
        for(i=1;i<=n+1;i++)
            for(j=1;j<=m;j++){
                scanf("%d",&k);
                len[i][j][1]=k;
                len[i][j+1][2]=k;
            }
        memset(pe,true,sizeof(pe));
        n++;
        m++;
        dij(1,1);    
        for(i=1;i<=tc;i++)bfs(cy[i][0],cy[i][1]);
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
                for(k=1;k<=4;k++)if(len[i][j][k]){
                    x=i+c[k][0];y=j+c[k][1];
                    if(k==1){
                        nl[2*i-1][2*j][1]=nl[2*x-1][2*y-1][2]=len[i][j][k];
                        nl[2*i][2*j][1]=nl[2*x][2*y-1][2]=len[i][j][k];
                        if(!pe[i][j][k]){
                            nl[2*i-1][2*j][3]=nl[2*i][2*j][4]=1ll<<60;
                            nl[2*i-1][2*j+1][3]=nl[2*i][2*j+1][4]=1ll<<60;
                        }
                    }
                    if(k==3){
                        nl[2*i][2*j-1][3]=nl[2*x-1][2*y-1][4]=len[i][j][k];
                        nl[2*i][2*j][3]=nl[2*x-1][2*y][4]=len[i][j][k];
                        if(!pe[i][j][k]){
                            nl[2*i][2*j-1][1]=nl[2*i][2*j][2]=1ll<<60;
                            nl[2*i+1][2*j-1][1]=nl[2*i+1][2*j][2]=1ll<<60;
                        }
                    }
                }
        for(i=1;i<=tc;i++){
            x=cy[i][0];y=cy[i][1];
            nl[2*x][2*y][1]=nl[2*x][2*y+1][2]=1ll<<60;nl[2*x][2*y-1][1]=nl[2*x][2*y][2]=1ll<<60;nl[2*x][2*y+1][1]=nl[2*x][2*y+2][2]=1ll<<60;
            nl[2*x+1][2*y][1]=nl[2*x+1][2*y+1][2]=1ll<<60;nl[2*x+1][2*y-1][1]=nl[2*x+1][2*y][2]=1ll<<60;nl[2*x+1][2*y+1][1]=nl[2*x+1][2*y+2][2]=1ll<<60;
            nl[2*x][2*y][3]=nl[2*x+1][2*y][4]=1ll<<60;nl[2*x-1][2*y][3]=nl[2*x][2*y][4]=1ll<<60;nl[2*x+1][2*y][3]=nl[2*x+2][2*y][4]=1ll<<60;
            nl[2*x][2*y+1][3]=nl[2*x+1][2*y+1][4]=1ll<<60;nl[2*x-1][2*y+1][3]=nl[2*x][2*y+1][4]=1ll<<60;nl[2*x+1][2*y+1][3]=nl[2*x+2][2*y+1][4]=1ll<<60;
        }
        nl[1][1][3]=nl[2][1][4]=1ll<<60;nl[1][2][3]=nl[2][2][3]=1ll<<60;
        nl[1][1][1]=nl[1][2][2]=1ll<<60;nl[2][1][1]=nl[2][2][2]=1ll<<60;
        for(i=1;i<=2*n;i++)
            for(j=1;j<=2*m;j++)
                for(k=1;k<=4;k++)len[i][j][k]=nl[i][j][k];
        n*=2;m*=2;
        dij(1,2);
        printf("%lld
    ",d[2][1]);
    }
  • 相关阅读:
    轻松记账方法(A)
    个人学习进度(第八周)
    个人学习进度(第八周)
    Web版四则运算
    个人学习进度(第七周)
    个人学习进度(第六周)
    数组的子数组和最大值
    个人学习进度(第五周)
    个人学习进度(第四周)
    个人学习进度(第三周)
  • 原文地址:https://www.cnblogs.com/applejxt/p/4424898.html
Copyright © 2020-2023  润新知