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\n",d[2][1]);
}

 

posted on 2015-04-14 14:50  razorjxt  阅读(324)  评论(0编辑  收藏  举报