Salvar al soldado Ryan (ruta más corta, compresión de estado)

Inserte la descripción de la imagen aquí

Idea: Para encontrar la distancia más corta al punto N, M, cuando hay una puerta, debe usar la llave correspondiente para abrir la puerta, luego usamos dis [i] [j] para indicar que el estado de la llave se mantuvo en la posición del número i es j La distancia más corta. De acuerdo con el número de identificación de la clave, inicializamos el estado de la Clave como Clave = 1 << id-1, podemos encontrar que cuando hay una clave en esta posición, nuestro estado cambiará state = state (original) | y luego ver si necesita ser actualizado. Dis puede obtener la ecuación de transferencia dis [i] [estado] = dis [i] [estado (original) | tecla], y luego moverse hacia arriba, abajo, izquierda y derecha. en movimiento, necesitamos juzgar si hay una puerta. Cuando hay una puerta, necesitamos Determinar si hay una llave para esta posición en el estado donde tenemos la llave en esta posición. Si la posición es W, veremos que 1 >> w-1 & 1 es 0, lo que significa que no hay llave de puerta. El mapa del problema es relativamente irregular. Primero, cambiamos la posición de cada punto x, y a un número, y luego ingresamos la posición de la pared y la puerta. Si es una pared, no importa, si es una puerta, cree un borde y use el número de la puerta. Peso, para juzgar si hay una puerta en esta posición más adelante, agreguemos todos los números de las posiciones de las puertas y paredes ingresadas en el conjunto. Más tarde, agregará bordes a toda la imagen. Si este número no se usa en este momento, significa que están entre Hay lados, cada número generalmente tiene 4 lados, así que use la matriz dir.

Código:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
 
using namespace std;
typedef long long ll;
#define SIS std::ios::sync_with_stdio(false)
#define space putchar(' ')
#define enter putchar('\n')
#define lson root<<1
#define rson root<<1|1
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
const int mod=1e9+7;
const int N=2e5+5;
const int inf=0x7f7f7f7f;

int gcd(int a,int b)
{
    
    
    return b==0?a:gcd(b,a%b);
}
 
ll lcm(ll a,ll b)
{
    
    
    return a*(b/gcd(a,b));
}
 
template <class T>
void read(T &x)
{
    
    
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-')
            op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op)
        x = -x;
}
template <class T>
void write(T x)
{
    
    
    if(x < 0)
        x = -x, putchar('-');
    if(x >= 10)
         write(x / 10);
    putchar('0' + x % 10);
}
ll qsm(int a,int b,int p)
{
    
    
    ll res=1%p;
    while(b)
    {
    
    
        if(b&1)
            res=res*a%p;
        a=1ll*a*a%p;
        b>>=1;
    }
    return res;
}
struct node
{
    
    
    int to,nex,w;
}edge[400];
const int P=1<<10;
int head[400],dis[400][P],vis[400][P];
int g[400][400],key[400];
int tot;
int n,m,s,k;
set<PII> edges;
void add(int u,int v,int w)
{
    
    
    edge[tot].w=w;
    edge[tot].to=v;
    edge[tot].nex=head[u];
    head[u]=tot++;
}
int dir[4][2]={
    
    {
    
    1,0},{
    
    -1,0},{
    
    0,1},{
    
    0,-1}};

void build()
{
    
    
    for(int i=1;i<=n;i++)
     for(int j=1;j<=m;j++)
      for(int u=0;u<4;u++)
      {
    
    
          int x=i+dir[u][0],y=j+dir[u][1];
          if(!x||x>n||!y||y>m)continue;
          int a=g[i][j],b=g[x][y];
          if(edges.count({
    
    a,b})==0){
    
    
              add(a,b,0);
              add(b,a,0);
          }
      }
   
}

int bfs()
{
    
    
    memset(dis,inf,sizeof dis);
    memset(vis,0,sizeof vis);
    dis[1][0]=0;
    deque<PII> q;
    q.push_back({
    
    1,0});
    while(q.size())
    {
    
    
        
        PII now=q.front();q.pop_front();
        int u=now.first,sta=now.second;
        //cout<<u<<endl;
        if(vis[u][sta])continue;
        vis[u][sta]=1;
        if(u==n*m) return dis[u][sta];
        
        if(key[u])
        {
    
    
            int state=sta|key[u];
            if(dis[u][state]>dis[u][sta])
            {
    
    
                dis[u][state]=dis[u][sta];
                q.push_front({
    
    u,state});
            }
        }
       // cout<<"2--"<<u<<endl;
        for(int i=head[u];~i;i=edge[i].nex)
        {
    
    
            int v=edge[i].to,w=edge[i].w;
            if(w && !(sta >> w - 1 & 1) ) continue;
            if(dis[v][sta]>dis[u][sta]+1)
            {
    
    
                dis[v][sta]=dis[u][sta]+1;
                q.push_back({
    
    v,sta});
            }
        }

    }
    return -1;

}




int main()
{
    
    
   cin>>n>>m>>s>>k;
   memset(head,-1,sizeof head);
   
   for(int i=1,t=1;i<=n;i++)
       for(int j=1;j<=m;j++)
           g[i][j]=t++;

   while(k--)
   {
    
    
       int x1,x2,y1,y2,op;
       cin>>x1>>y1>>x2>>y2>>op;
       int a=g[x1][y1],b=g[x2][y2];
       edges.insert({
    
    a,b});edges.insert({
    
    b,a});
       if(op){
    
    
           add(a,b,op);add(b,a,op);
       }

   }
    build();

   int rz;
   cin>>rz;
   while(rz--)
   {
    
    
       int x,y,c;
       cin>>x>>y>>c;
       key[g[x][y]]|=1<<c-1;
      

   }
  
   cout<<bfs()<<endl;


   return 0;

}


Supongo que te gusta

Origin blog.csdn.net/qq_43619680/article/details/112983015
Recomendado
Clasificación