2018.07.22 洛谷P3106 GPS的决斗Dueling GPS's(最短路)

传送门
图论模拟题。

这题直接写3个(可以压成一个) spfa s p f a ,前两个把题上的 p,q p , q 分别当做边权来跑,然后最后一次将前两次标记过两次的边边权设为0,标记过一次的边权设为1,没标记过的边权设为0就行了。

代码如下:

#include<bits/stdc++.h>
#define N 100005
#define M 500005
using namespace std;
struct Node{int v,next,w;}e1[M<<1],e2[M<<1],e[M<<1];
int first1[N],first2[N],first[N],d1[N],d2[N],p1[N],p2[N],d[N],n,m,cnt=0,cnt1=0,cnt2=0;
bool in1[N],in2[N],in[N]; 
inline int read(){
    int ans=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    return ans;
}
inline void add1(int u,int v,int w){
    e1[++cnt1].v=v;
    e1[cnt1].w=w;
    e1[cnt1].next=first1[u];
    first1[u]=cnt1;
}
inline void add2(int u,int v,int w){
    e2[++cnt2].v=v;
    e2[cnt2].w=w;
    e2[cnt2].next=first2[u];
    first2[u]=cnt2;
}
inline void add(int u,int v,int w){
    e[++cnt].v=v;
    e[cnt].w=w;
    e[cnt].next=first[u];
    first[u]=cnt;
}
inline void spfa1(int s=n){
    queue<int>q;
    memset(d1,0x3f3f3f3f,sizeof(d1));
    memset(in1,false,sizeof(in1));
    d1[s]=0,q.push(s);
    while(!q.empty()){
        int x=q.front();
        q.pop();
        in1[x]=false;
        for(int i=first1[x];i;i=e1[i].next){
            int v=e1[i].v;
            if(d1[v]>d1[x]+e1[i].w){
                d1[v]=d1[x]+e1[i].w;
                p1[v]=i;
                if(!in1[v])in1[v]=true,q.push(v);
            }
        }
    }
}
inline void spfa2(int s=n){
    queue<int>q;
    memset(d2,0x3f3f3f3f,sizeof(d2));
    memset(in2,false,sizeof(in2));
    d2[s]=0,q.push(s);
    while(!q.empty()){
        int x=q.front();
        q.pop();
        in2[x]=false;
        for(int i=first2[x];i;i=e2[i].next){
            int v=e2[i].v;
            if(d2[v]>d2[x]+e2[i].w){
                d2[v]=d2[x]+e2[i].w;
                p2[v]=i;
                if(!in2[v])in2[v]=true,q.push(v);
            }
        }
    }
}
inline void spfa(int s=1){
    queue<int>q;
    memset(d,0x3f3f3f3f,sizeof(d));
    memset(in,false,sizeof(in));
    d[s]=0,q.push(s);
    while(!q.empty()){
        int x=q.front();
        q.pop();
        in[x]=false;
        for(int i=first[x];i;i=e[i].next){
            int v=e[i].v,w=e[i].w;
            if(p1[x]==i)--w;
            if(p2[x]==i)--w;
            if(d[v]>d[x]+w){
                d[v]=d[x]+w;
                if(!in[v])in[v]=true,q.push(v);
            }
        }
    }
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=m;++i){
        int u=read(),v=read(),p=read(),q=read();
        add1(v,u,p),add2(v,u,q),add(u,v,2);
    }
    spfa1(),spfa2(),spfa();
    printf("%d",d[n]);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dueling DQN是一种基于DQN算法的改进算法,它能够更高效地学习状态价值函数。与传统的DQN只会更新某个动作的Q值不同,Dueling DQN会同时更新状态价值函数和动作优势函数,从而更加频繁、准确地学习状态价值函数。具体来说,Dueling DQN将Q值分解为状态价值函数和动作优势函数两部分,这样就可以在学习状态价值函数时避免重复计算动作优势函数,从而提高学习效率。 下面是Dueling DQN的代码实现: ```python import torch import torch.nn as nn import torch.optim as optim import numpy as np class DuelingDQN(nn.Module): def __init__(self, input_size, output_size): super(DuelingDQN, self).__init__() self.input_size = input_size self.output_size = output_size self.fc1 = nn.Linear(input_size, 128) self.fc2 = nn.Linear(128, 128) self.fc3_adv = nn.Linear(128, output_size) self.fc3_val = nn.Linear(128, 1) def forward(self, x): x = torch.relu(self.fc1(x)) x = torch.relu(self.fc2(x)) adv = self.fc3_adv(x) val = self.fc3_val(x).expand(x.size(0), self.output_size) x = val + adv - adv.mean(1, keepdim=True).expand(x.size(0), self.output_size) return x class Agent(): def __init__(self, input_size, output_size, gamma=0.99, lr=0.001): self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu") self.gamma = gamma self.model = DuelingDQN(input_size, output_size).to(self.device) self.optimizer = optim.Adam(self.model.parameters(), lr=lr) self.loss_fn = nn.MSELoss() def act(self, state, epsilon=0.0): if np.random.random() < epsilon: return np.random.choice(self.model.output_size) state = torch.FloatTensor(state).unsqueeze(0).to(self.device) q_values = self.model(state) return q_values.argmax().item() def learn(self, state, action, reward, next_state, done): state = torch.FloatTensor(state).unsqueeze(0).to(self.device) next_state = torch.FloatTensor(next_state).unsqueeze(0).to(self.device) action = torch.LongTensor([action]).to(self.device) reward = torch.FloatTensor([reward]).to(self.device) q_value = self.model(state).gather(1, action.unsqueeze(1)) next_q_value = self.model(next_state).max(1)[0].unsqueeze(1) expected_q_value = reward + self.gamma * next_q_value * (1 - done) loss = self.loss_fn(q_value, expected_q_value.detach()) self.optimizer.zero_grad() loss.backward() self.optimizer.step() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值