BZOJ 1556 墓地秘密

Posted on 2016-09-05 15:05  ziliuziliu  阅读(127)  评论(0编辑  收藏  举报

2333333333333333333333333333333333333333333333

啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊

辣鸡出题人辣鸡出题人辣鸡出题人辣鸡出题人辣鸡出题人辣鸡出题人

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define inf 1000000007
using namespace std;
int n,m,t,wh[105][105],dis[105][105],x[20],y[20],tab[20][5][20][5],pre[105][105],fro[20][5][20][5],f[(1<<16)+500][25][5];
int dx[]={0,-1,0,1,0},dy[]={0,0,1,0,-1};
bool map[105][105],vis[105][105];
char s[105];
queue <int> q;
void reset()
{
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            dis[i][j]=inf;
    while (!q.empty()) q.pop();
    memset(vis,false,sizeof(vis));
}
bool judge(int x,int y)
{
    if ((x>=1) && (x<=n) && (y>=1) && (y<=m) && (!map[x][y]))
        return true;
    return false;
}
void spfa(int pos,int dir)
{
    memset(pre,0,sizeof(pre));
    if (!judge(x[pos]+dx[dir],y[pos]+dy[dir])) return;
    dis[x[pos]+dx[dir]][y[pos]+dy[dir]]=0;vis[x[pos]+dx[dir]][y[pos]+dy[dir]]=true;
    q.push(x[pos]+dx[dir]);q.push(y[pos]+dy[dir]);
    while (!q.empty())
    {
        int hx,hy;
        hx=q.front();q.pop();hy=q.front();q.pop();
        int p=1;
        while (judge(hx-p,hy))
        {
            if ((dis[hx-p][hy]>dis[hx][hy]+1) || ((dis[hx-p][hy]==dis[hx][hy]+1) && (wh[hx-p][hy]==3)))
            {
                dis[hx-p][hy]=dis[hx][hy]+1;
                pre[hx-p][hy]=3;
                if (!vis[hx-p][hy])
                {
                    vis[hx-p][hy]=true;
                    q.push(hx-p);q.push(hy);
                }
            }   
            p++;
        }
        p=1;
        while (judge(hx+p,hy))
        {
            if ((dis[hx+p][hy]>dis[hx][hy]+1) || ((dis[hx+p][hy]==dis[hx][hy]+1) && (wh[hx+p][hy]==1)))
            {
                dis[hx+p][hy]=dis[hx][hy]+1;
                pre[hx+p][hy]=1;
                if (!vis[hx+p][hy])
                {
                    vis[hx+p][hy]=true;
                    q.push(hx+p);q.push(hy);
                }
            }   
            p++;
        }
        p=1;
        while (judge(hx,hy-p))
        {
            if ((dis[hx][hy-p]>dis[hx][hy]+1) || ((dis[hx][hy-p]==dis[hx][hy]+1) && (wh[hx][hy-p]==2)))
            {
                dis[hx][hy-p]=dis[hx][hy]+1;
                pre[hx][hy-p]=2;
                if (!vis[hx][hy-p])
                {
                    vis[hx][hy-p]=true;
                    q.push(hx);q.push(hy-p);
                }
            }   
            p++;
        }
        p=1;
        while (judge(hx,hy+p))
        {
            if ((dis[hx][hy+p]>dis[hx][hy]+1) || ((dis[hx][hy+p]==dis[hx][hy]+1) && (wh[hx][hy+p]==4)))
            {
                dis[hx][hy+p]=dis[hx][hy]+1;
                pre[hx][hy+p]=4;
                if (!vis[hx][hy+p])
                {
                    vis[hx][hy+p]=true;
                    q.push(hx);q.push(hy+p);
                }
            }   
            p++;
        }
        vis[hx][hy]=false;
    }
}
void get_tab(int pos,int dir)
{
    for (int i=1;i<=t+1;i++)
        for (int j=1;j<=4;j++)
        {
            if (judge(x[i]+dx[j],y[i]+dy[j]))
            {
                tab[pos][dir][i][j]=dis[x[i]+dx[j]][y[i]+dy[j]];
                fro[pos][dir][i][j]=pre[x[i]+dx[j]][y[i]+dy[j]];
            }
        }
}
int main()
{
    //freopen("secret.in","r",stdin);
    //freopen("secret.out","w",stdout);
    memset(map,false,sizeof(map));
    scanf("%d%d%d",&n,&m,&t);
    for (int i=1;i<=n;i++)
    {
        scanf("\n%s",s);
        for (int j=0;j<m;j++)
            if (s[j]=='#') map[i][j+1]=true;
    }
    for (int i=1;i<=t;i++)
    {
        scanf("%d%d",&x[i],&y[i]);
        map[x[i]][y[i]]=true;
    }
    for (int i=1;i<=t;i++)
    {
        for (int j=1;j<=4;j++)
        {
            if (judge(x[i]+dx[j],y[i]+dy[j]))
                wh[x[i]+dx[j]][y[i]+dy[j]]=j;
        }
    }
    scanf("%d%d",&x[t+1],&y[t+1]);
    for (int i=1;i<=t+1;i++)
        for (int j=0;j<=4;j++)
            for (int k=1;k<=t;k++)
                for (int l=1;l<=4;l++)
                    tab[i][j][k][l]=inf;
    for (int i=1;i<=t;i++)
    {
        for (int j=1;j<=4;j++)
        {
            reset();
            spfa(i,j);
            get_tab(i,j);
        }
    }
    reset();
    spfa(t+1,0);
    for (int i=1;i<=t+1;i++)
        for (int j=1;j<=4;j++)
        {
            if (judge(x[i]+dx[j],y[i]+dy[j]))
            {
                tab[t+1][0][i][j]=dis[x[i]+dx[j]][y[i]+dy[j]];
                fro[t+1][0][i][j]=pre[x[i]+dx[j]][y[i]+dy[j]];
            }
        }
    int top=(1<<t)-1;
    for (int s=1;s<=top;s++)
        for (int i=1;i<=t;i++)
            for (int j=1;j<=4;j++)
                f[s][i][j]=inf;
    for (int i=1;i<=t;i++)
        for (int j=1;j<=4;j++)
        {
            if (fro[t+1][0][i][j]!=j)
                f[1<<(i-1)][i][j]=tab[t+1][0][i][j]+1;
            else f[1<<(i-1)][i][j]=tab[t+1][0][i][j];
        }
    for (int ss=1;ss<=top;ss++)
    {
        for (int i=1;i<=t;i++)
        {
            if (ss&(1<<(i-1)))
            {
                for (int j=1;j<=t;j++)
                {
                    if (ss&(1<<(j-1))) continue;
                    for (int k=1;k<=4;k++)
                        for (int l=1;l<=4;l++)
                        {
                            if (tab[i][k][j][l]==inf) continue;
                            if (fro[i][k][j][l]!=l)
                                f[ss|1<<(j-1)][j][l]=min(f[ss|1<<(j-1)][j][l],f[ss][i][k]+tab[i][k][j][l]+1);
                            else f[ss|1<<(j-1)][j][l]=min(f[ss|1<<(j-1)][j][l],f[ss][i][k]+tab[i][k][j][l]);
                        }
                }
            }
        }
    }
    int ans=inf;
    for (int i=1;i<=t;i++)
        for (int j=1;j<=4;j++)
            ans=min(ans,f[top][i][j]);
    printf("%d\n",ans);
    return 0;
}