其他分享
首页 > 其他分享> > 2019暑假集训8.22(problem3.chess)

2019暑假集训8.22(problem3.chess)

作者:互联网

第一问每个点八个方向连边后(敌军点边权为0,空点边权为1)用dijkstra跑一下就行。

主要是第二问,难点在于只是走的空点不同才能算作不同的路。

如:

只能算作一条路径。

于是考虑建新图,重新连边,白点(空点)直接和相邻的白点相连

注意!如图中1,2号点,可能存在两个白点之间有多个黑点,而这时候只能连一条边,不然最短路计数时会多计,在连边的时候打上vis标记即可

处理方式是:对于每一个点都去看与它相连的边。

 

 

#include<bits/stdc++.h>
#define N 52
#define INF 9000000000000000000
#define inf 2100000000
#define LL long long
using namespace std;
int read()
{
    int x=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    return x*f;
}
struct EDGE{
    int nextt,to,val;
}w[N*N*N*N];
struct EdgeE{
    int nextt,to;
}w2[N*N*N*N];
struct qnode{
    int v,c;
    qnode(int _v=0,int _c=0):v(_v),c(_c){}
    bool operator <(const qnode &r)const 
    {return r.c<c;} 
};
int ud[]={1,1,-1,-1,2,2,-2,-2},lr[]={2,-2,2,-2,1,-1,1,-1};
int sx,sy,ex,ey,sord,eord,n,m;
int mp[N][N],head[N*N],head2[N*N],xu[N][N],dis[N*N],vis[N*N],vv[N*N],kong[N*N];
LL dep[N*N],num[N*N];
LL ans=INF;
int ge=0,rua=0,rua2=0;
LL tot=0;
void add(int a,int b,int c)
{
    rua++;
    w[rua].nextt=head[a];
    w[rua].to=b;
    w[rua].val=c;
    head[a]=rua;
}
void add2(int a,int b)//建新图 
{
    rua2++;
    w2[rua2].nextt=head2[a];
    w2[rua2].to=b;
    head2[a]=rua2;
}
void init()
{
    for(int x=1;x<=m;++x)
      for(int y=1;y<=n;++y)
          for(int i=0;i<8;++i)
          {
            int xx=x+lr[i],yy=y+ud[i];
            if(xx>=1&&xx<=m&&yy>=1&&yy<=n&&mp[xx][yy]!=2)//八个方向连边 
              add(xu[x][y],xu[xx][yy],(mp[xx][yy]!=1&&mp[xx][yy]!=4));
        }
}
void dij(int s,int t)//跑最短路 
{
    priority_queue<qnode>q;
    for(int i=1;i<=ge;++i)dis[i]=inf;
    dis[s]=0;
    q.push(qnode(s,0));
    while(!q.empty())
    {
        int x=q.top().v;q.pop();
        if(vis[x])continue;
        vis[x]=1;
        for(int i=head[x];i;i=w[i].nextt)
        {
            int v=w[i].to;
            if(!vis[v]&&dis[v]>dis[x]+w[i].val)
            {
                dis[v]=dis[x]+w[i].val;
                q.push(qnode(v,dis[v]));
            }
        }
    }
} 
void dfs(int x,int last)//每个点都去连边,只连一层 
{
    for(int i=head[x];i;i=w[i].nextt)
    {
        int v=w[i].to;
        if(kong[v]||v==eord)
        {
            if(!vv[v]){vv[v]=1;add2(last,v);continue;}
        }
        else dfs(v,last);
    }
}
/*void dfs(int root,int rt) 
{
    if(rt==sord&&root!=rt) return;
    if(kong[rt]&&rt!=root) {add2(root,rt);return;}
    for(int i=head[rt];i;i=w[i].nextt)
    {
        int v=w[i].to;
        if(!vv[v]) vv[v]=1,dfs(root,v);
    }
}*/
void ways(int s,int t)//最短路计数 
{
    queue<int>que;
    memset(vis,0,sizeof(vis));
    num[s]=1;vis[s]=1;que.push(s);
    while(!que.empty())
    {
        int x=que.front();que.pop();
        for(int i=head2[x];i;i=w2[i].nextt)
        {
            int v=w2[i].to;//printf(">>%d\n",v);
            if(!vis[v])dep[v]=dep[x]+1,num[v]=num[x],vis[v]=1,que.push(v);
            else if(dep[v]==dep[x]+1)num[v]=(num[v]+num[x]);
        }
    }
    printf("%lld\n",num[t]);
}
int main()
{
//    freopen("chess.in","r",stdin);
//    freopen("chess.out","w",stdout);
    m=read(),n=read();
    for(int i=1;i<=m;++i)
      for(int j=1;j<=n;++j)
      {
          mp[i][j]=read();
          xu[i][j]=++ge;
          if(mp[i][j]==0||mp[i][j]==3)kong[ge]=1;
          int x=mp[i][j];
          if(x==3)sx=i,sy=j,sord=xu[sx][sy];
          else if(x==4)ex=i,ey=j,eord=xu[ex][ey];
      }
    init();
    dij(sord,eord);
    printf("%d\n",dis[eord]);
    for(int i=1;i<=n*n;++i)
      if(kong[i])memset(vv,0,sizeof(vv)),dfs(i,i);
    ways(sord,eord);
} 
/*
4 5
0 0 0 0 1
0 0 3 0 0
0 0 0 4 0
0 1 0 0 0
*/
View Code

 

标签:rt,&&,int,problem3,vis,num,2019,8.22,que
来源: https://www.cnblogs.com/yyys-/p/11402043.html